package com.ruifu.proj.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fhzncloud.cloud.admin.api.feign.RemoteTenantService;
import com.fhzncloud.cloud.admin.api.vo.TenantVO;
import com.fhzncloud.cloud.common.core.constant.SecurityConstants;
import com.fhzncloud.cloud.common.core.util.R;
import com.fhzncloud.cloud.common.core.util.StringUtils;
import com.fhzncloud.cloud.common.security.service.CloudUser;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.ruifu.common.config.CodeType;
import com.ruifu.common.eneity.BaseEntityPlus;
import com.ruifu.common.po.*;
import com.ruifu.common.utils.AssignorsUtils;
import com.ruifu.common.utils.BeanConverter;
import com.ruifu.common.utils.ProjectCodeUtils;
import com.ruifu.common.utils.PtOrderComparator;
import com.ruifu.common.vo.PageResultVO;
import com.ruifu.proj.dto.ptmain.*;
import com.ruifu.proj.dto.ptobject.PmPtInsertObjectDTO;
import com.ruifu.proj.dto.ptobject.PmPtInsertTypeDTO;
import com.ruifu.proj.enums.PlanEnum;
import com.ruifu.proj.mapper.*;
import com.ruifu.proj.permission.*;
import com.ruifu.proj.service.PmPTypeService;
import com.ruifu.proj.service.PmPtMainService;
import com.ruifu.proj.service.PmPtObjectService;
import com.ruifu.proj.util.BeanUtil;
import com.ruifu.proj.vo.page.ProjPage;
import com.ruifu.proj.vo.page.ProjPageResultVO;
import com.ruifu.proj.vo.planver.PmPlanVerVO;
import com.ruifu.proj.vo.pmPtObject.PmPtObjectResultVO;
import com.ruifu.proj.vo.pmtasklog.PmTaskLogVO;
import com.ruifu.proj.vo.ptmain.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author nyr
 * @create 2019/9/18
 */
@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class PmPtMainServiceImpl implements PmPtMainService {
    //角色： 创建人，执行人，中间委托人，流程参与人，项目经理，负责人

    //状态： A 未  B 待启动(等待中)  C 启动中 D 待审核 E 已关闭(通过) F冻结
    /*定义状态*/
    private String[] status = {"A", "B", "C", "D", "E"};

    /*定义操作*/
    private Integer[][] permissionMap =
            {
                    /*操作权限*/
                    //创建人(第一委托人)
                    {
                            PermissionFounder.NOT_ISSUED,
                            PermissionFounder.NOT_STARTED,
                            PermissionFounder.IN_OPERATION,
                            PermissionFounder.TO_BE_AUDITED,
                            PermissionFounder.CLOSED,
                            PermissionFounder.FROZEN
                    },
                    //执行人
                    {
                            PermissionExecutor.NOT_ISSUED,
                            PermissionExecutor.NOT_STARTED,
                            PermissionExecutor.IN_OPERATION,
                            PermissionExecutor.TO_BE_AUDITED,
                            PermissionExecutor.CLOSED,
                            PermissionExecutor.FROZEN
                    },
                    //中间委托人
                    {
                            PermissionMiddleClient.NOT_ISSUED,
                            PermissionMiddleClient.NOT_STARTED,
                            PermissionMiddleClient.IN_OPERATION,
                            PermissionMiddleClient.TO_BE_AUDITED,
                            PermissionMiddleClient.CLOSED,
                            PermissionMiddleClient.FROZEN
                    },
                    //流程参与人
                    {
                            PermissionProcessParticipants.NOT_ISSUED,
                            PermissionProcessParticipants.NOT_STARTED,
                            PermissionProcessParticipants.IN_OPERATION,
                            PermissionProcessParticipants.TO_BE_AUDITED,
                            PermissionProcessParticipants.CLOSED,
                            PermissionProcessParticipants.FROZEN
                    },
                    //项目经理
                    {
                            PermissionProjectManager.NOT_ISSUED,
                            PermissionProjectManager.NOT_STARTED,
                            PermissionProjectManager.IN_OPERATION,
                            PermissionProjectManager.TO_BE_AUDITED,
                            PermissionProjectManager.CLOSED,
                            PermissionProjectManager.FROZEN
                    },
                    //上级任务负责人
                    {
                            PermissionSuperiorExecutor.NOT_ISSUED,
                            PermissionSuperiorExecutor.NOT_STARTED,
                            PermissionSuperiorExecutor.IN_OPERATION,
                            PermissionSuperiorExecutor.TO_BE_AUDITED,
                            PermissionSuperiorExecutor.CLOSED,
                            PermissionSuperiorExecutor.FROZEN
                    }
            };
    @Autowired(required = false)
    private PmPtMainMapper pmPtMainMapper;

    @Autowired(required = false)
    private PmPlanVerMapper pmPlanVerMapper;

    @Autowired(required = false)
    private PmPhaseTaskMapper pmPhaseTaskMapper;

    @Autowired(required = false)
    private PmPTypeMapper pmPTypeMapper;

    @Autowired(required = false)
    private PmPtCondTaskMapper pmPtCondTaskMapper;

    @Autowired(required = false)
    private PmActiveMainMapper pmActiveMainMapper;

    @Autowired(required = false)
    private PmTaskLogMapper pmTaskLogMapper;

    @Autowired(required = false)
    private PmPMemberMapper pmPMemberMapper;

    @Autowired(required = false)
    private PmPtObjectMapper pmPtObjectMapper;

    @Autowired(required = false)
    private PmPtObjectService pmPtObjectService;

    @Autowired
    private PmPtObjectServiceImpl pmPtObjectServiceImpl;

    @Autowired(required = false)
    private PmTaskAuditMapper pmTaskAuditMapper;
    @Autowired
    private PmPTypeService pmPTypeService;

    @Autowired
    private PmPtObjectService PmPtObjectService;

    @Autowired
    RemoteTenantService remoteTenantService;


    /**
     * 联合查询
     *
     * @param pageNum
     * @param pageSize
     * @param pmPtMainQueryDTO
     * @param cloudUser
     * @return
     */
    @Override
    public PageResultVO findByQuery(int pageNum, int pageSize, PmPtMainQueryDTO pmPtMainQueryDTO, CloudUser cloudUser) {
        PageHelper.startPage(pageNum, pageSize);
        Page<PmPtMain> page = (Page<PmPtMain>) pmPtMainMapper.findByQuery(pmPtMainQueryDTO, cloudUser);
        /*PO转VO*/
        List<PmPtMainVO> pmPtMainVOList = BeanConverter.copyList(page.getResult(), PmPtMainVO.class);

        for (PmPtMainVO pmPtMainVO : pmPtMainVOList) {
            //设置项目管理委托人
            pmPtMainVO.setPtAssignorId(Long.parseLong(pmPtMainVO.getPtAssignors().substring(pmPtMainVO.getPtAssignors().lastIndexOf(",") + 1)));
            List<PmActiveMain> pmActiveMainList = pmActiveMainMapper.findByPtId(pmPtMainVO.getPtId());
            if (CollectionUtils.isNotEmpty(pmActiveMainList)) {
                //获取最新执行记录
                PmActiveMain pmActiveMain = pmActiveMainList.get(pmActiveMainList.size() - 1);
                //设置实际开始实际，实际结束时间
                pmPtMainVO.setPvStartTime(pmActiveMain.getPvStartTime());
                pmPtMainVO.setPvEndTime(pmActiveMain.getPvEndTime());
            }
        }
        return new PageResultVO(page.getTotal(), pmPtMainVOList);
    }

    /**
     * 新建项目、模板
     *
     * @param pmPtMainInsertDTO
     * @param cloudUser
     */
    @Override
    public Long insert(PmPtMainInsertDTO pmPtMainInsertDTO, CloudUser cloudUser) {
        //判断扩展属性集是否为空
        if (pmPtMainInsertDTO.getPtPropsets() == null || "".equals(pmPtMainInsertDTO.getPtPropsets())) {
            pmPtMainInsertDTO.setPtPropsets("{}");
        }
        /*DTO转PO*/
        PmPtMain pmPtMain = BeanConverter.copyProperties(pmPtMainInsertDTO, PmPtMain.class);
        /*设置缺省字段默认值*/
        //父Id
        pmPtMain.setPtPId(0L);
        //设置为项目
        pmPtMain.setPtPtm("P");
        //项目任务委托人用户ID链
        pmPtMain.setPtAssignors(cloudUser.getId() + "");
        //里程碑标记
        pmPtMain.setPtMilestone(false);
        //任务状态
        if (pmPtMain.getPtIsTemplate()) {
            //模板初始状态
            pmPtMain.setPtStatus("TA");
        } else {
            //项目初始状态
            pmPtMain.setPtStatus("A");
        }
        //项目进度
        pmPtMain.setPtProgress(0);
        //排序字段
        pmPtMain.setPtOrder("1");
        pmPtMain.setPtCreator(Long.valueOf(cloudUser.getId()));
        pmPtMainMapper.insert(pmPtMain, cloudUser);
        return pmPtMain.getPtId();
    }

    /**
     * 新建游离态项目
     *
     * @param pmFreePtMainInsertDTO
     * @param cloudUser
     */
    @Override
    public void create(PmFreePtMainInsertDTO pmFreePtMainInsertDTO, CloudUser cloudUser) {
        log.info("Feign远程调用SysTenantService开始……");
        TenantVO tenantVO = new TenantVO();
        tenantVO.setName(pmFreePtMainInsertDTO.getPtName());
        tenantVO.setType("0");//创建的类型，1-群组；0-项目
        tenantVO.setUserId(cloudUser.getId());
        //Feign远程调用SysTenantService创建游离态账套
        R r = remoteTenantService.createProjectTenant(tenantVO, SecurityConstants.FROM_IN);
        if (r == null || r.getData() == null) {
            throw new RuntimeException("游离态账套不存在");
        }
        log.info("Feign远程调用SysTenantService==>>{}", JSON.toJSON(r.getData()));
        Map map = (Map) r.getData();
        PmPtMain pmPtMain = new PmPtMain();
        pmPtMain.setPtSetSid(Long.valueOf((Integer) map.get("id")));
        pmPtMain.setPtName(pmFreePtMainInsertDTO.getPtName());
        /*设置缺省字段默认值*/
        //父Id
        pmPtMain.setPtPId(0L);
        //设置为项目
        pmPtMain.setPtPtm("P");
        //项目任务委托人用户ID链
        pmPtMain.setPtAssignors(cloudUser.getId() + "");
        //里程碑标记
        pmPtMain.setPtMilestone(false);
        //项目初始状态
        pmPtMain.setPtStatus("A");
        //项目进度
        pmPtMain.setPtProgress(0);
        //排序字段
        pmPtMain.setPtOrder("1");
        Integer i = pmPtMainMapper.insertFree(pmPtMain, cloudUser);
        if (i < 0) {
            throw new RuntimeException("新增项目失败");
        }
        /*初始化项目类型以及任务类型*/
        insertIntoPmPTypeDb(pmPtMain);

    }

    private void insertIntoPmPTypeDb(PmPtMain pmPtMain) {
        //初始化一条项目类型
        init(pmPtMain, "P");
        //初始化一条任务类型
        init(pmPtMain, "T");

    }

    private void init(PmPtMain pmPtMain, String type) {
        PmPType pType = new PmPType();
        if (pType.getPyPsetsdef() == null || "".equals(pType.getPyPsetsdef())) {
            pType.setPyPsetsdef("{}");
        }
        pType.setPyCode(type);
        pType.setPyName(pmPtMain.getPtName());
        pType.setPyPhase("");
        pType.setPyCreator(pmPtMain.getPtCreator());
        pType.setPyCreDate(new Date());
        pType.setPyLastUpdator(pmPtMain.getPtLastUpdator());
        pType.setPyLastUpdate(new Date());
        pType.setPyOwner(pmPtMain.getPtOwner());
        pType.setPyOrgId(pmPtMain.getPtOrgId());
        pType.setPyDelFlag(false);
        pType.setPySetSid(pmPtMain.getPtSetSid());
        pmPTypeMapper.insertSelective(pType);
    }


    /**
     * 甘特图中新建任务
     *
     * @param pmPtMainGTDTO
     * @param cloudUser
     */
    public Long insertGTTask(PmPtMainGTDTO pmPtMainGTDTO, CloudUser cloudUser) {
        /*DTO转PO*/
        PmPtMain pmPtMain = BeanConverter.copyProperties(pmPtMainGTDTO, PmPtMain.class);
        //判断扩展属性集是否为空
        if (pmPtMain.getPtPropsets() == null || "".equals(pmPtMain.getPtPropsets())) {
            pmPtMain.setPtPropsets("{}");
        }
        //项目任务委托人用户ID链
        // pmPtMain.setPtAssignors(cloudUser.getId() + ""); 2020.5.21 委托人 新建取当前用户 升降级传参
        String ptAssignors = pmPtMainGTDTO.getPtAssignors();
        Long ptCreator = pmPtMainGTDTO.getPtCreator();
        if (org.apache.commons.lang3.StringUtils.isNotBlank(ptAssignors)) {
            pmPtMain.setPtAssignors(ptAssignors);
        } else {
            pmPtMain.setPtAssignors(cloudUser.getId() + "");
        }
        //2020.5.21 升级之后，创建人也要变更
        if (ptCreator != null) {
            pmPtMain.setPtCreator(ptCreator);
        } else {
            pmPtMain.setPtCreator(Long.valueOf(cloudUser.getId()));
        }


        //里程碑标记
        pmPtMain.setPtMilestone(false);
        //任务状态
        pmPtMain.setPtStatus("A");
        //任务类别
        pmPtMain.setPtPtm("T");
        //保密级别
        pmPtMain.setPtSafeLevel(1L);
        //项目特性
        pmPtMain.setPtSpecial("N");
        /*设置是否作为模板*/
        //查询所属项目
        PmPtMain pmPtMainParent = this.recursionProject(pmPtMain.getPtPId());

        //判断是否不属于项目
        if (pmPtMainParent != null) {
            if (pmPtMainParent.getPtIsTemplate()) {
                //模板任务
                pmPtMain.setPtIsTemplate(true);
                //根据生成器生成模板任务编号
                pmPtMain.setPtCode(ProjectCodeUtils.getCode(CodeType.TEMPLATE_TASK));
            } else {
                //普通任务
                pmPtMain.setPtIsTemplate(false);
                pmPtMain.setPtCode(ProjectCodeUtils.getCode(CodeType.TASK));
                //============================================================
                //查询当前任务的父任务
            }

            //删除标记
            pmPtMain.setPtDelFlag(false);
            //项目进度
            pmPtMain.setPtProgress(0);
            pmPtMain.setPtRemark("无");
            //保存记录获取该记录的id
            pmPtMainMapper.insert(pmPtMain, cloudUser);
            //新建启动条件
            PmTaskAudit pmTaskAudit = new PmTaskAudit();
            /*存入日志*/
            this.insertPmTaskLog(pmPtMain, pmTaskAudit, cloudUser, "新建任务");
        }
        return pmPtMain.getPtId();
    }

    /**
     * 封装Log方法
     *
     * @param pmPtMain
     * @param cloudUser
     * @param pmTaskAudit
     * @return
     */
    private void insertPmTaskLog(PmPtMain pmPtMain, PmTaskAudit pmTaskAudit, CloudUser cloudUser, String text) {
        PmTaskLog pmTasklog = new PmTaskLog();
        if (pmTaskAudit.getPaId() != null) {
            //审核表id
            pmTasklog.setPaId(pmTaskAudit.getPaId());
        }
        //获取被操作的任务id
        pmTasklog.setPlPtid(pmPtMain.getPtId());
        //获取任务名称
        pmTasklog.setPlTname(pmPtMain.getPtName());
        //获取操作人id
        pmTasklog.setPlUserid(Long.valueOf(cloudUser.getId()));
        //获取操作时间
        pmTasklog.setPlLogtime(new Date());
        pmTasklog.setPlLogtext(text);
        pmTaskLogMapper.insert(pmTasklog, cloudUser);
    }

    public List<PmPtMain> recursion(Long ptPId, List<PmPtMain> list) {
        //查询当前任务的父任务
        PmPtMain parentPmPtMain = pmPtMainMapper.findById(ptPId);
        //list.add(parentPmPtMain);
        if (parentPmPtMain != null) {
            //判断父任务是否是任务
            if ("T".equals(parentPmPtMain.getPtPtm())) {
                //继续查询父任务
                parentPmPtMain = this.recursionProject(parentPmPtMain.getPtPId());
                list.add(parentPmPtMain);
            }
        }
        return list;
    }


    /**
     * 修改甘特图结构+（新建任务+修改结构）
     *
     * @param pmPtMainGTDTOList
     * @param cloudUser
     */
    @Override
    public void updateList(Long ptPid, List<PmPtMainGTDTO> pmPtMainGTDTOList, CloudUser cloudUser) {

        List<PmPtMain> PmPtMainList = new ArrayList<>();

        if (null != ptPid) {
            //不在甘特图，需重构入参
            if (CollectionUtils.isNotEmpty(pmPtMainGTDTOList)) {
                Long ptPId = pmPtMainGTDTOList.get(0).getPtPId();
                //递归查询父任务，并存放到集合中
                this.recursion(ptPId, PmPtMainList);
            }
            for (PmPtMain pmPtMain : PmPtMainList) {
                PmPtMainGTDTO pmPtMainGTDTO = new PmPtMainGTDTO();
                BeanUtils.copyProperties(pmPtMain, pmPtMainGTDTO);
                //根据ptorder来构造level
                int i = pmPtMainGTDTO.getPtOrder().split("\\.").length - 1;
                pmPtMainGTDTO.setLevel(i);
                pmPtMainGTDTOList.add(pmPtMainGTDTO);
            }
            Collections.reverse(pmPtMainGTDTOList);
        }


        //AP,BP,CP,DP
        String[] assignorStatus = {"D", "P", "AP", "BP", "CP", "DP", "E"};//分别是待审核，已冻结，已完成
        String[] excuteStatus = {"A", "D", "P", "AP", "BP", "CP", "DP", "E"};//分别是未下达，待审核，已冻结，已完成
        //2020.5.20修改
        PmPtMain parent = null;
        //得到根节点
        if (pmPtMainGTDTOList != null && pmPtMainGTDTOList.size() > 0) {
            if (null == ptPid) {
                //如果在甘特图  不会传ptPid  根项目直接取第一个
                parent = pmPtMainMapper.findById(pmPtMainGTDTOList.get(0).getPtId());
            } else {
                //如果在子任务，根项目通过传来的ptpid查到
                parent = pmPtMainMapper.findById(ptPid);
            }

            if (parent.getPtAssignors().contains(String.valueOf(cloudUser.getId()))) {
                //a)当前用户是甘特图根项目/任务的委托人,甘特图根项目/任务状态为“待审核、已冻结、已完成”时：不能做任何修改
                for (int i = 0; i < assignorStatus.length; i++) {
                    if (assignorStatus[i].equals(parent.getPtStatus())) {
                        throw new RuntimeException("当前根项目/任务状态锁定，不能做任何修改！");
                    }
                }
            } else if (Long.valueOf(cloudUser.getId()).equals(parent.getPtExecuter())) {
                //b)当前用户是甘特图根项目/任务的执行人,若甘特图根项目/任务状态为“未下达、待审核、已冻结、已完成”时：不能做任何修改。
                for (int i = 0; i < excuteStatus.length; i++) {
                    if (excuteStatus[i].equals(parent.getPtStatus())) {
                        throw new RuntimeException("当前根项目/任务状态锁定，不能做任何修改！");
                    }
                }
            }
        }
        /*关系声明*/
        //级别 -> 键：级别 值：id
        Map<Integer, Long> levelMap = new HashMap<>();
        //依赖 -> 键：id 值：依赖项
        Map<Long, String> dependencyMap = new HashMap<>();
        //排序 -> 键：id 值：排序号
        Map<Integer, String> orderMap = new HashMap<>();
        //设置顶级排序为当前第一条记录的排序号
        orderMap.put(0, pmPtMainGTDTOList.get(0).getPtOrder());
        //记录上一级别
        Integer upLevel = 0;
        //同级序号默认为1
        int number = 1;
        /*遍历传入的集合*/
        for (PmPtMainGTDTO pmPtMainGTDTO : pmPtMainGTDTOList) {

            //2020.5.23新增 依赖项入参为空  则赋值[]
            String ptDependency = pmPtMainGTDTO.getPtDependency();
            if (StringUtils.isBlank(ptDependency)) {
                ptDependency = "[]";
            }
            //获取当前的级别
            Integer level = pmPtMainGTDTO.getLevel();
            //排除第一个记录
            if (level != 0) {
                if (upLevel > level) {
                    /*上一级叔*/
                    //在map中获取当前级别的序号
                    String order = orderMap.get(level);
                    //切割序号获得同级序号并增加1
                    number = Integer.parseInt(order.substring(order.lastIndexOf(".") + 1)) + 1;
                } else if (upLevel < level) {
                    /*上一级子*/
                    //重置同级序号number
                    number = 1;
                } else if (upLevel.equals(level)) {
                    /*上一级平级*/
                    //同级序号增1
                    number++;
                }
                //重新赋值上一条记录的级别
                upLevel = level;
                //设置当前记录DTO的级别序号
                //如果上一层发生升降级，不要影响后续
                pmPtMainGTDTO.setPtOrder(orderMap.get(level - 1) + "." + number);
                //为级别序号集合重新增、改值
                orderMap.put(level, pmPtMainGTDTO.getPtOrder());
            }
            //判断该对象是否有id(新建)
            if (pmPtMainGTDTO.getPtId() == null) {

                //得到根节点
                //PmPtMainGTDTO pmPtMainGTDTO1 = pmPtMainGTDTOList.get(0);
                //根节点下面的任务列表
                List<PmPtMain> pmPtMainLists = pmPtMainMapper.findByPtPId(parent.getPtId());
                //取出树的名称
                List<String> ptNameList = pmPtMainLists.stream().map(PmPtMain::getPtName).collect(Collectors.toList());
                //判断任务列表是否为空
                if (pmPtMainLists.isEmpty()) {
                    //设置父id
                    pmPtMainGTDTO.setPtPId(levelMap.get(level - 1));
                    //新建
                    Long ptId = this.insertGTTask(pmPtMainGTDTO, cloudUser);
                    //甘特图集合设置主键
                    pmPtMainGTDTO.setPtId(ptId);
                    //填充级别列表
                    levelMap.put(level, ptId);
                    //填充依赖项表

                    dependencyMap.put(ptId, ptDependency);
                    continue;
                } else {
                    //不包含则新建
                    if (!ptNameList.contains(pmPtMainGTDTO.getPtName())) {
                        //设置父id
                        pmPtMainGTDTO.setPtPId(levelMap.get(level - 1));
                        //新建
                        Long ptId = this.insertGTTask(pmPtMainGTDTO, cloudUser);
                        //甘特图集合设置主键
                        pmPtMainGTDTO.setPtId(ptId);
                        //填充级别列表
                        levelMap.put(level, ptId);
                        //填充依赖项表
                        dependencyMap.put(ptId, ptDependency);
                        continue;
                    }
                }
            }
            /*填充依赖项表*/
            dependencyMap.put(pmPtMainGTDTO.getPtId(), ptDependency);
            /*删除启停条件*/
            pmPtCondTaskMapper.delete(Wrappers.<PmPtCondTask>lambdaQuery()
                    .eq(PmPtCondTask::getPcSId, pmPtMainGTDTO.getPtId())
                    .eq(BaseEntityPlus::getSetSid, cloudUser.getTenantId()));
            //填充级别列表
            levelMap.put(level, pmPtMainGTDTO.getPtId());
            //获取数据库对象
            PmPtMain pmPtMain = pmPtMainMapper.findById(pmPtMainGTDTO.getPtId());
            /*PO转DTO*/
            PmPtMainGTDTO ptMainDTO = BeanConverter.copyProperties(pmPtMain, PmPtMainGTDTO.class);
            ptMainDTO.setLevel(level);
            //设置记录的新父id
            if (pmPtMainGTDTO.getPtPId() != 0) {
                Long ptPId = levelMap.get(level - 1);
                if (ptPId != null) {
                    pmPtMainGTDTO.setPtPId(ptPId);
                }
            }

            /*合并*/
            BeanConverter.copyProperties(pmPtMainGTDTO, pmPtMain);
            pmPtMainMapper.update(pmPtMain, cloudUser);
        }
        /*获取依赖项转换规则*/
        String rule = this.getRule(BeanConverter.copyList(pmPtMainGTDTOList, PmPtMain.class), true);
        /*依赖项处理*/
        dependencyMap.forEach((pcSId, dependency) -> {
            String dependencyJson = AssignorsUtils.convertDependency(dependency, rule);
            ArrayList<String> list = JSON.parseObject(dependencyJson, ArrayList.class);
            list.forEach(pcPId -> {
                PmPtCondTask pmPtCondTask = new PmPtCondTask();
                pmPtCondTask.setPcPId(Long.parseLong(pcPId));
                pmPtCondTask.setPcSId(pcSId);
                pmPtCondTaskMapper.insert(pmPtCondTask);
            });
        });
    }


    /**
     * 根据id查询任务或者项目详情
     *
     * @param ptId
     * @return
     */
    @Override
    public PmPtMainVO findById(Long ptId) {
        //得到项目或任务对象
        PmPtMain pmPtMain = pmPtMainMapper.findById(ptId);
        log.info("根据id查询任务或者项目详情:{}", JSONObject.toJSONString(pmPtMain));
        /*PO转VO*/
        return BeanConverter.copyProperties(pmPtMain, PmPtMainVO.class);
    }

    /**
     * 根据主键id删除项目和包含的子任务和模板
     *
     * @param ptId
     * @param cloudUser
     */
    @Override
    public void deleteById(Long ptId, CloudUser cloudUser) {
        /*根据id查询该项目(任务)*/
        PmPtMain pmPtMain = pmPtMainMapper.findById(ptId);
        /*递归删除*/
        this.recurveDelete(pmPtMain, cloudUser);
    }


    /**
     * 校验编号是否存在
     * 根据项目编号查询
     *
     * @param ptCode
     * @return
     */
    @Override
    public Boolean findByPtCode(String ptCode) {
        return pmPtMainMapper.findByPtCode(ptCode) == null;
    }

    /**
     * 根据父任务id查询任务列表
     *
     * @param ptId
     * @return
     */
    @Override
    public List<PmPtMainVO> findByPtPId(Long ptId) {
        List<PmPtMain> pmPtMainList = pmPtMainMapper.findByPtPId(ptId);
        return BeanConverter.copyList(pmPtMainList, PmPtMainVO.class);
    }

    /**
     * 分页查询项目/任务的子任务列表
     *
     * @param ptId
     * @param pageNum
     * @param pageSize
     * @param cloudUser
     * @return
     */
    @Override
    public PageResultVO findTasksPage(Long ptId, int pageNum, int pageSize, CloudUser cloudUser) {
        PageHelper.startPage(pageNum, pageSize);
        Page<PmPtMain> page = ((Page<PmPtMain>) pmPtMainMapper.findByPtPId(ptId));
        List<PmPtMainVO> list = new ArrayList<>();
        for (PmPtMain pmPtMain : page.getResult()) {
            PmPtMainVO pmPtMainVO = BeanConverter.copyProperties(pmPtMain, PmPtMainVO.class);
            Integer permission = findPermissionByUserIdAndPtId(Long.valueOf(cloudUser.getId()), pmPtMainVO.getPtId());
            pmPtMainVO.setPermission(permission);
            list.add(pmPtMainVO);
        }
        return new PageResultVO(page.getTotal(), list);
    }

    /**
     * 项目详情   新页面   一键保存基本属性  计划   输入输出文档  2020.5.18
     *
     * @param savePmPtMainAttributeDTO
     * @param cloudUser
     */
    @Override
    @Transactional
    public void saveAll(SavePmPtMainAttributeDTO savePmPtMainAttributeDTO, CloudUser cloudUser) {
        //保存项目属性
        this.saveAttributeById(savePmPtMainAttributeDTO.getPmPtMainAttributeDTO(), cloudUser);

        Long ptId = savePmPtMainAttributeDTO.getPmPtMainAttributeDTO().getPtId();

        //文档类别关联项目id
        List<PmPtInsertTypeDTO> pmPtInsertTypeDTOList = savePmPtMainAttributeDTO.getPmPtInsertTypeDTOList();
        //设置文档关联项目id
        List<PmPtInsertObjectDTO> objectDTOList = savePmPtMainAttributeDTO.getPmPtInsertObjectDTOList();

        //删除旧数据
        List<PmPtObject> list = pmPtObjectMapper.findByPtId(ptId, cloudUser);
        if (CollectionUtils.isNotEmpty(list)) {
            for (PmPtObject pmPtObject : list) {
                //pmPtObjectMapper.deleteById(pmPtObject.getPoId(),cloudUser);
                pmPtObject.setPoDelFlag(true);
                pmPtObjectMapper.update(pmPtObject, cloudUser);
            }
        }

        //添加新的数据
        List<PmPtInsertObjectDTO> pmPtInsertObjectDTOList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(pmPtInsertTypeDTOList)) {
            for (PmPtInsertTypeDTO pmPtInsertTypeDTO : pmPtInsertTypeDTOList) {
                //清空主键
                pmPtInsertTypeDTO.setPoId(null);
                PmPtInsertObjectDTO pmPtInsertObjectDTO = new PmPtInsertObjectDTO();
                BeanUtils.copyProperties(pmPtInsertTypeDTO, pmPtInsertObjectDTO);
                pmPtInsertObjectDTOList.add(pmPtInsertObjectDTO);
            }
            pmPtInsertObjectDTOList.forEach(x -> x.setPoPtId(ptId));
            pmPtObjectService.insertPL(pmPtInsertObjectDTOList, cloudUser);
        }

        //添加新的数据
        //清空主键
        if (CollectionUtils.isNotEmpty(objectDTOList)) {
            //添加文档对象的时候，必须要有文档id，没有就剔除
            objectDTOList.removeIf(pmPtInsertObjectDTO -> pmPtInsertObjectDTO.getPoObjId() == null);
        }
        if (CollectionUtils.isNotEmpty(objectDTOList)) {
            objectDTOList.forEach(x -> x.setPoId(null));
            objectDTOList.forEach(x -> x.setPoPtId(ptId));
            //文档
            pmPtObjectService.insertPL(objectDTOList, cloudUser);
        }


    }

    @Override
    @Transactional
    public void insertAll(CreateNewPmPtMainDTO createNewPmPtMainDTO, CloudUser cloudUser) {
        //新增项目
        Long ptId = this.insert(createNewPmPtMainDTO.getPmPtMainInsertDTO(), cloudUser);

        //文档类型
        List<PmPtInsertTypeDTO> typeDTOList = createNewPmPtMainDTO.getPmPtInsertTypeDTOList();

        //文档对象
        List<PmPtInsertObjectDTO> objectDTOList = createNewPmPtMainDTO.getPmPtInsertObjectDTOList();

        //文档类型入库
        if (CollectionUtils.isNotEmpty(typeDTOList)) {
            //设置关联项目
            typeDTOList.forEach(x -> x.setPoPtId(ptId));

            List<PmPtInsertObjectDTO> pmPtInsertObjectDTOList = new ArrayList<>();

            for (PmPtInsertTypeDTO pmPtInsertTypeDTO : typeDTOList) {
                PmPtInsertObjectDTO pmPtInsertObjectDTO = new PmPtInsertObjectDTO();
                BeanUtils.copyProperties(pmPtInsertTypeDTO, pmPtInsertObjectDTO);
                pmPtInsertObjectDTOList.add(pmPtInsertObjectDTO);
            }
            pmPtObjectService.insertPL(pmPtInsertObjectDTOList, cloudUser);
        }

        if (CollectionUtils.isNotEmpty(objectDTOList)) {
            //2020.5.26  添加文档对象的时候，必须要有文档id，没有就剔除
            objectDTOList.removeIf(pmPtInsertObjectDTO -> pmPtInsertObjectDTO.getPoObjId() == null);
        }
        if (CollectionUtils.isNotEmpty(objectDTOList)) {
            objectDTOList.forEach(x -> x.setPoPtId(ptId));
            //文档对象
            pmPtObjectService.insertPL(objectDTOList, cloudUser);
        }
    }

    /**
     * 文档输入输出定义  需要获取项目子子孙孙任务列表
     *
     * @param ptId
     * @param cloudUser
     * @return
     */
    @Override
    public ProjPage findAllTasks(ProjPage page,Long ptId, CloudUser cloudUser) {
        /*查询子集列表*/
        PmPtMain pmMain = pmPtMainMapper.findById(ptId);
        List<PmPtMain> pmPtMainList = new ArrayList<>();
        this.recursionFindPtId(pmPtMainList, pmMain);
        //pmPtMainList.remove(pmMain);
        /*=====2020.5.27 改造分页=====*/
        //每页的开始数
        page.setStar((page.getCurrentPage() - 1) * page.getPageSize());
        //list的大小
        int count = pmPtMainList.size();
        //设置总页数
        page.setTotalPage(count % 10 == 0 ? count / 10 : count / 10 + 1);
        //对list进行截取
        page.setDataList(pmPtMainList.subList(page.getStar(),count-page.getStar()>page.getPageSize()?page.getStar()+page.getPageSize():count));
        page.setTotal(count);
        return page;
    }

    @Override
    public PmTaskAuditDTO findTaskAuditByPtId(Long ptId, Long paId, CloudUser cloudUser) {
        PmTaskAuditDTO pmTaskAuditDTO = new PmTaskAuditDTO();

        PmTaskAudit pmTaskAudit = pmTaskAuditMapper.findById(paId);
        if (null != pmTaskAudit) {
            BeanUtils.copyProperties(pmTaskAudit, pmTaskAuditDTO);
        }

        PmPtMain pmMain = pmPtMainMapper.findById(ptId);
        if (null != pmMain) {
            BeanUtils.copyProperties(pmMain, pmTaskAuditDTO);
        }

        return pmTaskAuditDTO;
    }


    @Override
    public void exchange(Integer sourceId, Integer targetId, String type, CloudUser cloudUser) {

        List<PmPType> sourceList = pmPTypeMapper.findByTenantId(sourceId, type);
        sourceList.forEach(x -> x.setPySetSid(Long.valueOf(targetId)));
        sourceList.forEach(x -> x.setPyId(null));
        for (PmPType pmPType : sourceList) {
            pmPTypeMapper.copy(pmPType, cloudUser);
        }
    }

    /**
     * 提交变更计划
     *
     * @param pvId
     */
    @Override
    public void submitPlan(Long pvId) {
        if (pvId == null) {
            throw new RuntimeException("参数异常");
        }
        PmPlanVer pmPlanVer = pmPlanVerMapper.findById(pvId);
        if (pmPlanVer == null) {
            throw new RuntimeException("参数异常，无此计划记录");
        }
        if (!pmPlanVer.getPvStatus().equals(PlanEnum.EDITING.getCode())) {
            throw new RuntimeException("只能提交状态为编辑中的计划变更");
        }
        pmPlanVer.setPvStatus(PlanEnum.WAITING_AUDIT.getCode());//改为待审核
        pmPlanVerMapper.update(pmPlanVer);
    }

    //编辑计划并更新
    @Override
    public void editPlan(PmPlanVerDTO pmPlanVerDTO, CloudUser cloudUser) {
        if (pmPlanVerDTO.getPvId() == null) {
            throw new RuntimeException("参数异常，id为空");
        }
        PmPlanVer pmPlanVer = pmPlanVerMapper.findById(pmPlanVerDTO.getPvId());
        if (pmPlanVer == null) {
            throw new RuntimeException("参数异常");
        }
        BeanUtil.copyPropertiesIgnoreNull(pmPlanVerDTO, pmPlanVer);
        pmPlanVerMapper.update(pmPlanVer);
    }

    //驳回计划变更
    @Override
    public void rejectPlan(Long pvId) {
        if (pvId == null) {
            throw new RuntimeException("参数异常");
        }
        PmPlanVer pmPlanVer = pmPlanVerMapper.findById(pvId);
        if (pmPlanVer == null) {
            throw new RuntimeException("参数异常，无此计划记录");
        }
        if (!pmPlanVer.getPvStatus().equals(PlanEnum.WAITING_AUDIT.getCode())) {
            throw new RuntimeException("只能驳回状态为待审核的计划变更");
        }
        pmPlanVer.setPvStatus(PlanEnum.EDITING.getCode());//驳回后  改为编辑中
        pmPlanVerMapper.update(pmPlanVer);

    }

    /**
     * 递归删除子任务及本身
     *
     * @param pmPtMain
     */
    private void recurveDelete(PmPtMain pmPtMain, CloudUser cloudUser) {
        /*伪删除当前任务*/
        //修改删除标记
        pmPtMain.setPtDelFlag(true);
        //更新
        pmPtMainMapper.update(pmPtMain, cloudUser);
        /*删除输入、输出文档*/
        List<PmPtObject> pmPtObjects = pmPtObjectMapper.findByPtId(pmPtMain.getPtId(), cloudUser);
        if (pmPtObjects != null && pmPtObjects.size() != 0) {
            for (PmPtObject pmPtObject : pmPtObjects) {
                pmPtObject.setPoDelFlag(true);
                pmPtObjectMapper.update(pmPtObject, cloudUser);
            }
        }
        /*删除计划*/
        pmPlanVerMapper.deleteByPtId(pmPtMain.getPtId());
        //判断是否是项目、模板项目
        if ("P".equals(pmPtMain.getPtPtm())) {
            /*删除阶段配置*/
            pmPhaseTaskMapper.deleteByPpPtId(pmPtMain.getPtId());
            /*删除团队配置*/
            List<PmPMember> pmPMembers = pmPMemberMapper.findByPbPtId(pmPtMain.getPtId(), cloudUser);
            if (pmPMembers != null && pmPMembers.size() != 0) {
                for (PmPMember pmPMember : pmPMembers) {
                    pmPMember.setPbDelFlag(true);
                    pmPMemberMapper.update(pmPMember, cloudUser);
                }
            }
        } else {
            /*删除启停条件*/
            //查询该任务是否作为其他任务的启停条件
            List<PmPtCondTask> pmPtCondTaskList = pmPtCondTaskMapper.selectList(Wrappers.<PmPtCondTask>lambdaQuery()
                    .eq(PmPtCondTask::getPcPId, pmPtMain.getPtId()));
            //判断是否为空
            if (pmPtCondTaskList != null && pmPtCondTaskList.size() != 0) {
                List<Long> collect = pmPtCondTaskList.stream().map(PmPtCondTask::getPcId).collect(Collectors.toList());
                pmPtCondTaskMapper.deleteBatchIds(collect);
            }
        }
        //判断是否不为模板
        if (!pmPtMain.getPtIsTemplate()) {
            /*删除执行记录*/
            List<PmActiveMain> pmActiveMains = pmActiveMainMapper.findByPtId(pmPtMain.getPtId());
            if (pmActiveMains != null && pmActiveMains.size() != 0) {
                //定义集合存储要删除的审核id
                List<Long> pvIdList = new ArrayList<>();
                for (PmActiveMain pmActiveMain : pmActiveMains) {
                    if (pmActiveMain.getPvEndTime() != null) {
                        //添加id到集合中
                        pvIdList.add(pmActiveMain.getPvId());
                    }
                    //修改删除标记
                    pmActiveMain.setPvDelFlag(true);
                    //更新数据库
                    pmActiveMainMapper.update(pmActiveMain, cloudUser);
                }
                /*删除审核记录*/
                if (pvIdList.size() != 0) {
                    pmTaskAuditMapper.deleteByPvId(pvIdList);
                }
            }
            /*删除日志 */
            pmTaskLogMapper.deleteByPtId(pmPtMain.getPtId());
        }
        /*查询该项目(任务)的子任务*/
        List<PmPtMain> ptMainList = pmPtMainMapper.findByPtPId(pmPtMain.getPtId());
        if (ptMainList != null && ptMainList.size() != 0) {
            //遍历
            for (PmPtMain ptMain : ptMainList) {
                //递归
                this.recurveDelete(ptMain, cloudUser);
            }
        }
    }

    /**
     * 修改运行状态
     *
     * @param ptId      任务ID
     * @param isPause   暂停标记
     * @param cloudUser 用户对象
     */
    @Override
    public void updateRunning(Long ptId, Boolean isPause, CloudUser cloudUser) {
        //根据id获取当前项目(任务)
        PmPtMain pmPtMain = pmPtMainMapper.findById(ptId);
        /*校验*/
        //判断暂停标记
        if (isPause) {
            /*暂停权限校验*/
            Integer permission = this.findPermissionByUserIdAndPtId(Long.valueOf(cloudUser.getId()), ptId);
            if ((permission & 8) != 8) {
                throw new RuntimeException("您的权限不足,无法暂停");
            }
            /*校验是否可以暂停*/
            if (pmPtMain.getPtStatus().contains("P")) {
                throw new RuntimeException("该任务已经暂停,无法继续暂停");
            }
        } else {
            /*重启权限校验*/
            Integer permission = this.findPermissionByUserIdAndPtId(Long.valueOf(cloudUser.getId()), ptId);
            if ((permission & 16) != 16) {
                throw new RuntimeException("您的权限不足,无法重启");
            }
            /*校验是否可以重启*/
            //根据父任务id查询父任务
            PmPtMain pmPtMainParent = pmPtMainMapper.findById(pmPtMain.getPtPId());
            if (pmPtMainParent != null && pmPtMainParent.getPtStatus().contains("P")) {
                throw new RuntimeException("父任务已暂停,无法恢复该任务!");
            }
        }
        //调用暂停与恢复方法
        this.pauseOrRecover(isPause, cloudUser, pmPtMain);
        /*查询当前任务的所有子任务列表*/
        //声明集合,用于存放子任务
        List<PmPtMain> sonPtMainList = new ArrayList<>();
        //递归查询所有子任务
        this.recursionFindPtId(sonPtMainList, pmPtMain);
        //移除该任务本身
        sonPtMainList.remove(pmPtMain);
        /*遍历子任务列表*/
        for (PmPtMain sonPtMain : sonPtMainList) {
            //调用暂停与恢复方法
            this.pauseOrRecover(isPause, cloudUser, sonPtMain);
        }
    }

    /**
     * 暂停与恢复
     *
     * @param isPause   暂停标记
     * @param cloudUser 用户对象
     * @param pmPtMain  任务对象
     */
    private void pauseOrRecover(Boolean isPause, CloudUser cloudUser, PmPtMain pmPtMain) {

        PmTaskAudit pmTaskAudit = new PmTaskAudit();

        //判断暂停标记
        if (isPause) {
            //暂停
            pmPtMain.setPtStatus(pmPtMain.getPtStatus() + "P");
            /*存入日志*/
            this.insertPmTaskLog(pmPtMain, pmTaskAudit, cloudUser, "暂停任务");
        } else {
            //重启
            pmPtMain.setPtStatus(pmPtMain.getPtStatus().substring(0, pmPtMain.getPtStatus().lastIndexOf("P")));
            /*存入日志*/
            this.insertPmTaskLog(pmPtMain, pmTaskAudit, cloudUser, "恢复任务");
        }
        //更新当前任务
        pmPtMainMapper.update(pmPtMain, cloudUser);
    }

    /**
     * 一键重启
     *
     * @param ptId      任务id
     * @param cloudUser 用户对象
     */
    @Override
    public void updateRestart(Long ptId, CloudUser cloudUser) {
        /*权限校验*/
        Integer permission = this.findPermissionByUserIdAndPtId(Long.valueOf(cloudUser.getId()), ptId);
        if ((permission & 16) != 16) {
            throw new RuntimeException("您的权限不足,无法重启");
        }
        //根据id获取当前项目(任务)
        PmPtMain pmPtMain = pmPtMainMapper.findById(ptId);
        /*校验是否可以重启*/
        //根据父任务id查询父任务
        PmPtMain pmPtMainParent = pmPtMainMapper.findById(pmPtMain.getPtPId());
        if (pmPtMainParent != null && pmPtMainParent.getPtStatus().contains("P")) {
            throw new RuntimeException("父任务已暂停,无法恢复该任务!");
        }
        //修改状态
        pmPtMain.setPtStatus(pmPtMain.getPtStatus().substring(0, 1));
        //更新到数据库
        pmPtMainMapper.update(pmPtMain, cloudUser);
        /*查询当前任务的所有子任务列表*/
        //声明集合,用于存放子任务
        List<PmPtMain> sonPtMainList = new ArrayList<>();
        //递归查询所有子任务
        this.recursionFindPtId(sonPtMainList, pmPtMain);
        //移除该任务本身
        sonPtMainList.remove(pmPtMain);
        /*遍历子任务列表*/
        for (PmPtMain sonPtMain : sonPtMainList) {
            //修改状态
            sonPtMain.setPtStatus(sonPtMain.getPtStatus().substring(0, 1));
            //更新到数据库
            pmPtMainMapper.update(sonPtMain, cloudUser);
        }
    }

    /**
     * 下达
     *
     * @param ptId
     * @param cloudUser
     */
    @Override
    public void issued(Long ptId, CloudUser cloudUser) {
        /*校验权限*/
        Integer permission = this.findPermissionByUserIdAndPtId(Long.valueOf(cloudUser.getId()), ptId);
        if ((permission & 256) != 256) {
            throw new RuntimeException("您的权限不足,无法下达");
        }
        PmPtMain pmPtMain = pmPtMainMapper.findById(ptId);
        /*校验执行人是否存在*/
        if (pmPtMain.getPtExecuter() == null) {
            throw new RuntimeException("请为该任务指定执行人");
        }
        doIssue(cloudUser, pmPtMain);
    }


    /**
     * 批量下达
     *
     * @param ptId      项目id
     * @param cloudUser
     * @return
     */
    @Override
    public R batchIssued(Long ptId, CloudUser cloudUser) {
        PmPtMain pmPtMain = pmPtMainMapper.findById(ptId);
        if (null == pmPtMain) {
            return null;
        }
        if (pmPtMain.getPtPtm().equals("P") && pmPtMain.getPtStatus().equals("A")) {
            //如果项目还没有下达，批量下达的时候，也要下达项目
            issued(ptId, cloudUser);
        }
        //查询当前项目的下级子任务
        List<PmPtMain> sonPtMainList = pmPtMainMapper.findByPtPId(pmPtMain.getPtId());
        Set<Long> sonTaskIdSet = null;
        //判断下级子任务是否不为空
        if (sonPtMainList != null && sonPtMainList.size() != 0) {
            sonTaskIdSet = sonPtMainList.stream().map(x -> x.getPtId()).collect(Collectors.toSet());
            sonTaskIdSet.forEach(x -> issuedEach(x, cloudUser));
        }
        return null;
    }

    @Override
    public R test(Long ptId, CloudUser cloudUser) {
        return R.ok(pmPtMainMapper.testSelect(ptId, cloudUser));
    }

    @Override
    public String changeLevel(Long ptId, String state, CloudUser cloudUser) {
        //当前任务
        PmPtMain currentPmPtMain = pmPtMainMapper.findById(ptId);
        if (ptId == null || StringUtils.isBlank(state) || currentPmPtMain == null) {
            //throw new RuntimeException("参数异常！");
            return "error";
        }
        //当前任务对应的父
        PmPtMain parentPmPtMain = pmPtMainMapper.findById(currentPmPtMain.getPtPId());
        //降级
        if ("down".equalsIgnoreCase(state)) {
            String s;
            //当前任务对应的父下面所有的子
            List<PmPtMain> sons = pmPtMainMapper.findByPtPIdOrder(parentPmPtMain.getPtId());
            log.info("当前任务所在子任务集合中的index:{}", sons.indexOf(currentPmPtMain));
            //todo 当前任务上一个任务，也就是将来的父,如何确定？
            String ptOrder = currentPmPtMain.getPtOrder();//1.2
            String lastNum = ptOrder.substring(ptOrder.lastIndexOf(".") + 1);//2

            String lastOrder = ptOrder.substring(0, ptOrder.lastIndexOf(".") + 1) + (Integer.parseInt(lastNum) - 1);//1.拼1
            PmPtMain pmPtMain = pmPtMainMapper.findByPtPIdAndPtOrder(currentPmPtMain.getPtPId(), lastOrder);
            if (null != pmPtMain) {
                List<PmPtMain> sonList = pmPtMainMapper.findByPtPIdOrder(pmPtMain.getPtId());
                if (CollectionUtils.isNotEmpty(sonList)) {
                    PmPtMain newestPmPtMain = sonList.get(sonList.size() - 1);
                    String ptCode = newestPmPtMain.getPtCode();
                    s = ptCode.substring(ptCode.lastIndexOf("-") + 1);//10
                    if (Integer.parseInt(s) < 9) {
                        s = ptCode.substring(0, ptCode.lastIndexOf("-") + 1) + "0" + (Integer.parseInt(s) + 1);
                    } else {
                        s = ptCode.substring(0, ptCode.lastIndexOf("-") + 1) + (Integer.parseInt(s) + 1);
                    }
                    currentPmPtMain.setPtCode(s);
                } else {
                    currentPmPtMain.setPtCode(pmPtMain.getPtCode() + "-01");
                }
                log.info("降级之后的当前任务的编码为：{}", currentPmPtMain.getPtCode());
                currentPmPtMain.setPtPId(pmPtMain.getPtId());//降级之后，当前任务的父id变为上一个任务的id
            }
        } else if ("up".equalsIgnoreCase(state)) {
            //升级
            String s;
            //当前任务的父任务的父
            PmPtMain grandFatherPmPtMain = pmPtMainMapper.findById(parentPmPtMain.getPtPId());
            //爷爷任务下面子任务集合
            List<PmPtMain> sonList = pmPtMainMapper.findByPtPIdOrder(grandFatherPmPtMain.getPtId());
            if (sonList.size() > 1) {
                PmPtMain newestPmPtMain = sonList.get(sonList.size() - 1);
                String ptCode = newestPmPtMain.getPtCode();
                s = ptCode.substring(ptCode.lastIndexOf("-") + 1);//10
                if (Integer.parseInt(s) < 9) {
                    s = ptCode.substring(0, ptCode.lastIndexOf("-") + 1) + "0" + (Integer.parseInt(s) + 1);
                } else {
                    s = ptCode.substring(0, ptCode.lastIndexOf("-") + 1) + (Integer.parseInt(s) + 1);
                }
                currentPmPtMain.setPtCode(s);
            }
            log.info("升级之后的当前任务的编码为：{}", currentPmPtMain.getPtCode());
            currentPmPtMain.setPtPId(grandFatherPmPtMain.getPtId());//升级之后,当前任务的父id变为当前父的父的id
        }
        pmPtMainMapper.update(currentPmPtMain, cloudUser);
        return currentPmPtMain.getPtCode();
    }


    private void issuedEach(Long x, CloudUser cloudUser) {
        /*校验权限*/
        Integer permission = this.findPermissionByUserIdAndPtId(Long.valueOf(cloudUser.getId()), x);
        if ((permission & 256) != 256) {
            throw new RuntimeException("您的权限不足,无法下达");
        }
        PmPtMain pmPtMain = pmPtMainMapper.findById(x);
        if (pmPtMain.getPtExecuter() != null) {
            //下达
            doIssue(cloudUser, pmPtMain);
        }
    }

    /**
     * 下达
     *
     * @param cloudUser
     * @param pmPtMain
     */
    private void doIssue(CloudUser cloudUser, PmPtMain pmPtMain) {
        //修改任务状态
        pmPtMain.setPtStatus("B");
        /*修改子任务负责人*/
        //递归修改子子孙孙委托人
        recursionUpdate(cloudUser, pmPtMain);
        pmPtMainMapper.update(pmPtMain, cloudUser);
        PmTaskAudit pmTaskAudit = new PmTaskAudit();
        /*存入日志*/
        this.insertPmTaskLog(pmPtMain, pmTaskAudit, cloudUser, "下达任务");
    }

    //递归修改子子孙孙任务的委托人
    public void recursionUpdate(CloudUser cloudUser, PmPtMain pmPtMain) {


        //查询当前任务的下级子任务
        List<PmPtMain> sonPtMainList = pmPtMainMapper.findByPtPId(pmPtMain.getPtId());
        //判断下级子任务是否不为空
        if (sonPtMainList != null && sonPtMainList.size() != 0) {

            //遍历子任务列表
            for (PmPtMain sonPtMain : sonPtMainList) {
                sonPtMain.setPtCreator(pmPtMain.getPtExecuter());
                //修改第一委托人
                sonPtMain.setPtAssignors(AssignorsUtils.updateFirstAssignor(sonPtMain.getPtAssignors(), pmPtMain.getPtExecuter()));
                //更新到数据库
                pmPtMainMapper.update(sonPtMain, cloudUser);

                //递归查询子任务
                //recursionUpdate(cloudUser,sonPtMain);
                List<PmPtMain> sunList = new ArrayList<>();
                recursionFindPtId(sunList, sonPtMain);
                sunList.remove(sonPtMain);

                for (PmPtMain ptMain : sunList) {
                    ptMain.setPtCreator(pmPtMain.getPtExecuter());
                    //修改第一委托人
                    ptMain.setPtAssignors(AssignorsUtils.updateFirstAssignor(sonPtMain.getPtAssignors(), pmPtMain.getPtExecuter()));
                    //更新到数据库
                    pmPtMainMapper.update(ptMain, cloudUser);
                }


            }
        }

    }


    /**
     * 启动
     * 【PmPtCondTask 启动条件】
     *
     * @param ptId
     * @param cloudUser
     */
    @Override
    public void start(Long ptId, CloudUser cloudUser) {
        /*校验权限*/
        Integer permission = this.findPermissionByUserIdAndPtId(Long.valueOf(cloudUser.getId()), ptId);
        if ((permission & 4096) != 4096) {
            throw new RuntimeException("您的权限不足,无法启动");
        }
        //根据id查询任务
        PmPtMain pmPtMain = pmPtMainMapper.findById(ptId);
        /*校验启停条件*/
        //查询当前任务的启动条件列表
        List<PmPtCondTask> pmPtCondTaskList = pmPtCondTaskMapper.selectList(Wrappers.<PmPtCondTask>lambdaQuery()
                .eq(PmPtCondTask::getPcSId, ptId));
        if (pmPtCondTaskList != null && pmPtCondTaskList.size() != 0) {
            for (PmPtCondTask pmPtCondTask : pmPtCondTaskList) {
                //根据前序任务id查询任务
                PmPtMain pmPtMainTask = pmPtMainMapper.findById(pmPtCondTask.getPcPId());
                //判断前序任务是否已经完成(E表示任务完成状态)
                if (!"E".equals(pmPtMainTask.getPtStatus())) {
                    //有一个条件不满足，抛出异常，无法启动
                    throw new RuntimeException("前序任务未完成,无法启动");
                }
            }
        }
        //判断该对象是否为任务
        if ("T".equals(pmPtMain.getPtPtm())) {
            /*校验父任务是否启动*/
            //查询父任务
            PmPtMain pmPtMainParent = pmPtMainMapper.findById(pmPtMain.getPtPId());
            //如果当前任务的父任务不为空且未启动则 当前任务无法启动
            if (pmPtMainParent != null && !"C".equals(pmPtMainParent.getPtStatus())) {
                throw new RuntimeException("上级任务未启动,无法启动");
            }
        }
        /*校验父任务状态*/
        //设置状态(启动)
        pmPtMain.setPtStatus("C");
        pmPtMain.setPtProgress(1);
        //更新项目或任务状态
        pmPtMainMapper.update(pmPtMain, cloudUser);
        /*新建任务实例*/
        PmActiveMain pmActiveMain = new PmActiveMain();
        //任务id
        pmActiveMain.setPvPtId(pmPtMain.getPtId());
        //开始时间
        pmActiveMain.setPvStartTime(new Date());
        //执行人
        pmActiveMain.setPvExecutor(cloudUser.getId().longValue());
        //插入数据库
        pmActiveMainMapper.insert(pmActiveMain, cloudUser);

        /*==========================2020.5.23 启动时项目初始化一条计划变更记录 =======================*/
        //保存计划的入参
        PmPtMainPlanDTO pmPtMainPlanDTO = new PmPtMainPlanDTO();

        PmPlanVerDTO pmPlanVerDTO = new PmPlanVerDTO();

        pmPlanVerDTO.setPvStartime(pmPtMain.getPtPlanStart());
        pmPlanVerDTO.setPvEndtime(pmPtMain.getPtPlanEnd());
        pmPlanVerDTO.setPvDuration(pmPtMain.getPtDays());//天数
        pmPlanVerDTO.setPvBudget(pmPtMain.getPtCost());//费用
        pmPlanVerDTO.setPvCostunit(pmPtMain.getPtCostunit());
        pmPlanVerDTO.setPvSubmittime(new Date());
        pmPlanVerDTO.setPvRemark("第一次发布");
        pmPlanVerDTO.setPvSubmittime(new Date());//申请时间
        pmPlanVerDTO.setPvPubdate(new Date());//审核时间
        pmPlanVerDTO.setPvStatus(PlanEnum.APPROVED.getCode());//已批准
        pmPtMainPlanDTO.setPtId(pmPtMain.getPtId());
        pmPtMainPlanDTO.setPtPlanEnd(pmPtMain.getPtPlanEnd());
        pmPtMainPlanDTO.setPtPlanStart(pmPtMain.getPtPlanStart());
        pmPtMainPlanDTO.setPmPlanVerDTO(pmPlanVerDTO);
        pmPtMainPlanDTO.setPvSubmitid(pmPtMain.getPtExecuter());
        this.savePlan(pmPtMainPlanDTO, cloudUser);
        /*==========================2020.5.23 启动时项目初始化一条计划变更记录 =======================*/

        PmTaskAudit pmTaskAudit = new PmTaskAudit();
        /*存入日志*/
        this.insertPmTaskLog(pmPtMain, pmTaskAudit, cloudUser, "启动任务");
    }

    /**
     * 提交
     * 【PmPtObject】关联数据对象
     *
     * @param ptId
     * @param cloudUser
     */
    @Override
    public void submit(Long ptId, CloudUser cloudUser) {
        PmPtMain pmPtMain = pmPtMainMapper.findById(ptId);
        /*权限校验*/
        Integer permission = this.findPermissionByUserIdAndPtId(Long.valueOf(cloudUser.getId()), ptId);
        if ((permission & 8192) != 8192) {
            throw new RuntimeException("您的权限不足,无法提交");
        }
        /*校验输出文档是否达到要求*/
        //查询输出文档类型集合
        List<PmPtObject> pmPtObjectDoccList = pmPtObjectMapper.findByPtIdAndPoIOType(pmPtMain.getPtId(), "O", true, cloudUser);
        //定义选择了必须的输出文档类型的类型id数组
        List<Long> poObjTypeIdList = new ArrayList<>();
        //筛选必须的类型集合并将类型存储
        pmPtObjectDoccList.stream()
                .filter(PmPtObject::getPoIsMust)
                .forEach(pmPtObject -> poObjTypeIdList.add(pmPtObject.getPoObjTypeId()));
        //判断勾选了必须的记录是否为0
        if (poObjTypeIdList.size() != 0) {
            //查询当前任务的输出文档
            List<PmPtObject> pmPtObjectDocVerList = pmPtObjectMapper.findByPtIdAndPoIOType(pmPtMain.getPtId(), "O", false, cloudUser);
            //定义所有输出文档的类型id数组
            Set<Long> poObjTypeIdSet = new HashSet<>();
            pmPtObjectDocVerList.forEach(pmPtObject -> poObjTypeIdSet.add(pmPtObject.getPoObjTypeId()));
            //遍历输出文档类型必须的id集合
            for (Long poObjTypeId : poObjTypeIdList) {
                //判断输出文档是否没有添加必须的类型文档
                if (!poObjTypeIdSet.contains(poObjTypeId)) {
                    throw new RuntimeException("该任务未能输出必须类型的文档,请添加必须类型文档后再提交");
                }
            }
        }
        /*子任务完成校验*/
        //查询子任务列表
        List<PmPtMain> sonPmPtMainList = pmPtMainMapper.findByPtPId(pmPtMain.getPtId());
        //声明子任务完成标记
        boolean flag = true;
        //遍历子任务列表
        for (PmPtMain sonPmPtMain : sonPmPtMainList) {
            if (!"E".equals(sonPmPtMain.getPtStatus())) {
                //修改子任务完成标记
                flag = false;
                //退出循环
                break;
            }
        }
        //判断完成标记
        if (!flag) {
            throw new RuntimeException("子任务未完成,无法提交");
        }
        //设置状态(提交)
        pmPtMain.setPtStatus("D");
        pmPtMain.setPtProgress(pmPtMain.getPtProgress() + 9);//提交后进度10%
        pmPtMainMapper.update(pmPtMain, cloudUser);
        /*查询该任务记录列表*/
        List<PmActiveMain> pmActiveMainList = pmActiveMainMapper.findByPtId(pmPtMain.getPtId());
        //获取最新执行记录
        PmActiveMain pmActiveMain = pmActiveMainList.get(pmActiveMainList.size() - 1);
        //设置提交时间
        pmActiveMain.setPvCommITime(new Date());
        //更新数据库
        pmActiveMainMapper.update(pmActiveMain, cloudUser);

        PmTaskAudit pmTaskAudit = new PmTaskAudit();
        /*存入日志*/
        this.insertPmTaskLog(pmPtMain, pmTaskAudit, cloudUser, "提交任务");
    }

    /**
     * 审核
     * 【审核不通过新增一条执行记录】
     *
     * @param pmPtMainAuditDTO
     * @param cloudUser
     */
    @Override
    public void updateAudit(PmPtMainAuditDTO pmPtMainAuditDTO, CloudUser cloudUser) {
        /*权限校验*/
        //判断是否有审核权限
        Integer permission = this.findPermissionByUserIdAndPtId(Long.valueOf(cloudUser.getId()), pmPtMainAuditDTO.getPtId());
        if ((permission & 32) != 32) {
            throw new RuntimeException("您的权限不足,无法审核");
        }
        //根据Id查询任务
        PmPtMain pmPtMain = pmPtMainMapper.findById(pmPtMainAuditDTO.getPtId());
        /*操作任务*/
        //审核选项控制
        if (null == pmPtMainAuditDTO.getIsStatus()) {
            throw new RuntimeException("您尚未选中通过或者驳回！");
        }
        //判断审核标记设置任务状态
        if (pmPtMainAuditDTO.getIsStatus()) {
            /*审核通过*/
            //判断审核链是否为空
            if (pmPtMain.getPtAudits() == null) {
                //添加当前审核用户到审核链
                pmPtMain.setPtAudits(cloudUser.getId() + "");
            } else {
                //拼接当前审核用户到原审核链
                pmPtMain.setPtAudits(pmPtMain.getPtAudits() + "," + cloudUser.getId());
            }
            //判断当前审核人是否为委托链第一人(即任务创建人)
            if (pmPtMain.getPtCreator().longValue() == cloudUser.getId()) {
                //即任务已经全部审核完成,修改任务状态
                pmPtMain.setPtStatus("E");
                //任务已经全部完成，修改进度为100%
                pmPtMain.setPtProgress(100);
            }
        } else {
            /*审核未通过*/
            //修改任务状态为运行中,需重新提交
            pmPtMain.setPtStatus("C");
            //清除审核链,等待重新提交后再次审核
            pmPtMain.setPtAudits(null);
        }
        //更新项目或任务状态
        pmPtMainMapper.update(pmPtMain, cloudUser);
        /*操作执行记录*/
        //查询该任务记录列表
        List<PmActiveMain> pmActiveMainList = pmActiveMainMapper.findByPtId(pmPtMain.getPtId());
        //获取最新执行记录
        PmActiveMain newPmActiveMain = pmActiveMainList.get(pmActiveMainList.size() - 1);
        //设置结束时间
        newPmActiveMain.setPvEndTime(new Date());
        //修改最新执行记录
        pmActiveMainMapper.update(newPmActiveMain, cloudUser);

        String paEvaluate = pmPtMainAuditDTO.getPmTaskAudit().getPaEvaluate();
        Float paTotal = pmPtMainAuditDTO.getPmTaskAudit().getPaTotal();
        paEvaluate = paEvaluate == null ? "无" : paEvaluate;
        paTotal = paTotal == null ? 0f : paTotal;


        /*存储审核信息*/
        /*DTO转PO*/
        PmTaskAudit pmTaskAudit = BeanConverter.copyProperties(pmPtMainAuditDTO.getPmTaskAudit(), PmTaskAudit.class);
        //将审核的执行记录Id设置到审核对象中
        pmTaskAudit.setPaPvId(newPmActiveMain.getPvId());
        //设置审核人
        pmTaskAudit.setPaExecuter(Long.valueOf(cloudUser.getId()));
        //设置审核时间
        pmTaskAudit.setPaAuditorTime(new Date());
        //设置审核结果
        pmTaskAudit.setPaResult(pmPtMainAuditDTO.getIsStatus());
        //存储审核信息到数据库
        pmTaskAuditMapper.insert(pmTaskAudit, cloudUser);

        Long paId = pmTaskAudit.getPaId();
        PmTaskAudit taskAudit = new PmTaskAudit();
        taskAudit.setPaId(paId);


        /*判断是否审核通过*/
        if (pmPtMainAuditDTO.getIsStatus()) {
            /*通过*/
            //存储日志信息
            this.insertPmTaskLog(pmPtMain, taskAudit, cloudUser,
                    "审核通过任务," + "【评价】：" + paEvaluate + ";" +
                            "【评分】：" + paTotal);
        } else {
            /*未通过*/
            //新增一条执行记录
            PmActiveMain pmActiveMain = new PmActiveMain();
            //设置任务id
            pmActiveMain.setPvPtId(newPmActiveMain.getPvPtId());
            //设置开始时间
            pmActiveMain.setPvStartTime(newPmActiveMain.getPvStartTime());
            //设置执行人
            pmActiveMain.setPvExecutor(cloudUser.getId().longValue());
            pmActiveMainMapper.insert(pmActiveMain, cloudUser);
            /*存入日志*/
            this.insertPmTaskLog(pmPtMain, taskAudit, cloudUser,
                    "审核未通过任务," + "【评价】：" + paEvaluate + ";" +
                            "【评分】：" + paTotal);
        }

    }

    /**
     * 撤销下达
     *
     * @param ptId      任务id
     * @param cloudUser 用户对象
     */
    @Override
    public void revocationIssued(Long ptId, CloudUser cloudUser) {
        /*校验权限*/
        Integer permission = this.findPermissionByUserIdAndPtId(Long.valueOf(cloudUser.getId()), ptId);
        if ((permission & 512) != 512) {
            throw new RuntimeException("您的权限不足,无法撤销下达");
        }
        //根据Id查询任务
        PmPtMain pmPtMain = pmPtMainMapper.findById(ptId);
        //修改任务状态 ->未下达
        pmPtMain.setPtStatus("A");
        //更新到数据库
        pmPtMainMapper.update(pmPtMain, cloudUser);

        PmTaskAudit pmTaskAudit = new PmTaskAudit();
        /*存储日志*/
        this.insertPmTaskLog(pmPtMain, pmTaskAudit, cloudUser, "撤销下达");
        /*修改下级任务权限*/
        //递归查询所有子任务,撤销下达的时候改变所有子子孙孙的状态 2020.05.16
        List<PmPtMain> pmPtMainList = new ArrayList<>();
        this.recursionFindPtId(pmPtMainList, pmPtMain);
        if (CollectionUtils.isNotEmpty(pmPtMainList)) {
            for (PmPtMain sonPtMain : pmPtMainList) {
                //修改创建人为当前撤销人
                sonPtMain.setPtCreator(Long.valueOf(cloudUser.getId()));
                //项目撤销下达，任务也要撤销下达
                sonPtMain.setPtStatus("A");
                //修改第一委托人
                sonPtMain.setPtAssignors(AssignorsUtils.updateFirstAssignor(sonPtMain.getPtAssignors(), Long.valueOf(cloudUser.getId())));
                //更新到数据库
                pmPtMainMapper.update(sonPtMain, cloudUser);
            }

        }

     /*   //查询当前任务的下级子任务
        List<PmPtMain> sonPtMainList = pmPtMainMapper.findByPtPId(pmPtMain.getPtId());
        //判断下级子任务是否不为空
        if (sonPtMainList != null && sonPtMainList.size() != 0) {
            //遍历子任务列表
            for (PmPtMain sonPtMain : sonPtMainList) {
                //修改创建人为当前撤销人
                sonPtMain.setPtCreator(Long.valueOf(cloudUser.getId()));
                //项目撤销下达，任务也要撤销下达
                sonPtMain.setPtStatus("A");
                //修改第一委托人
                sonPtMain.setPtAssignors(AssignorsUtils.updateFirstAssignor(sonPtMain.getPtAssignors(), Long.valueOf(cloudUser.getId())));
                //更新到数据库
                pmPtMainMapper.update(sonPtMain, cloudUser);
            }
        }*/
    }


    /**
     * 撤销转交
     *
     * @param ptId      任务Id
     * @param cloudUser 用户对象
     */
    @Override
    public void revocationDeliver(Long ptId, CloudUser cloudUser) {
        /*校验权限*/
        Integer permission = this.findPermissionByUserIdAndPtId(Long.valueOf(cloudUser.getId()), ptId);
        if ((permission & 128) != 128) {
            throw new RuntimeException("您的权限不足,无法撤销转交");
        }
        //根据Id查询任务
        PmPtMain pmPtMain = pmPtMainMapper.findById(ptId);
        //获取委托链
        String assignors = pmPtMain.getPtAssignors();
        //判断委托链是否除了创建人还有其他的
        if (!pmPtMain.getPtCreator().equals(assignors)) {
            //委托链从当前用户处删除之后的委托人
            pmPtMain.setPtAssignors(pmPtMain.getPtAssignors().substring(0, AssignorsUtils.getIndexOf(pmPtMain.getPtAssignors(), cloudUser.getId() + "") - 1));
        }
        //将负责人设置为撤销者
        pmPtMain.setPtExecuter(Long.valueOf(cloudUser.getId()));
        //更新到数据库
        pmPtMainMapper.update(pmPtMain, cloudUser);
        PmTaskAudit pmTaskAudit = new PmTaskAudit();

        /*存入日志*/
        this.insertPmTaskLog(pmPtMain, pmTaskAudit, cloudUser, "撤销转交");
    }

    /**
     * 查询任务日志
     *
     * @param ptId
     * @return
     */
    @Override
    public List<PmTaskLogVO> findByLog(Long ptId) {

        //该项目任务下所有日志
        List<PmTaskLog> pmTaskLogList = pmTaskLogMapper.findByPtId(ptId);
        List<PmTaskLogVO> pmTaskLogVOList = BeanConverter.copyList(pmTaskLogList, PmTaskLogVO.class);
        if (CollectionUtils.isNotEmpty(pmTaskLogVOList)) {
            for (PmTaskLogVO pmTaskLogVO : pmTaskLogVOList) {
                if (org.apache.commons.lang3.StringUtils.isNotBlank(pmTaskLogVO.getPlLogtext())) {
                    if (pmTaskLogVO.getPlLogtext().contains("审核通过")) {
                        //true  通过
                        pmTaskLogVO.setPassOrNot("yes");
                    } else if (pmTaskLogVO.getPlLogtext().contains("审核未通过")) {
                        pmTaskLogVO.setPassOrNot("no");
                    }
                }
            }
        }
        return pmTaskLogVOList;
    }

    /**
     * 转交
     *
     * @param ptId
     * @param ptExecuter 负责人id
     * @param cloudUser
     */
    @Override
    public void careOf(Long ptId, Long ptExecuter, CloudUser cloudUser) {
        /*存储项目转交信息*/
        //查询任务详情
        PmPtMain pmPtMain = pmPtMainMapper.findById(ptId);
        //当前用户是否是该任务的负责人
        Integer permission = this.findPermissionByUserIdAndPtId(Long.valueOf(cloudUser.getId()), ptId);
        if ((permission & 64) != 64) {
            throw new RuntimeException("您不是该任务的负责人,无法转交！");
        }
        if (!AssignorsUtils.isContains(pmPtMain.getPtAssignors(), pmPtMain.getPtExecuter() + "")) {
            //修改委托人链条
            pmPtMain.setPtAssignors(pmPtMain.getPtAssignors() + "," + pmPtMain.getPtExecuter());
        }
        //修改执行人
        pmPtMain.setPtExecuter(ptExecuter);
        //保存
        pmPtMainMapper.update(pmPtMain, cloudUser);
        PmTaskAudit pmTaskAudit = new PmTaskAudit();
        /*存入日志*/
        this.insertPmTaskLog(pmPtMain, pmTaskAudit, cloudUser, "转交任务");
    }

    /**
     * 查询项目详情
     *
     * @param ptId
     * @return
     */
    @Override
    public List<PmPtMainVO> findAllByPtId(Long ptId, CloudUser cloudUser) {
        /*查询子集列表*/
        PmPtMain pmMain = pmPtMainMapper.findById(ptId);
        List<PmPtMain> pmPtMainList = new ArrayList<>();
        this.recursionFindPtId(pmPtMainList, pmMain);
        Collections.sort(pmPtMainList, new PtOrderComparator());
        /*依赖项规则转换*/
        String rule = this.getRule(pmPtMainList, false);
        pmPtMainList.forEach(pmPtMain -> pmPtMain.setPtDependency(AssignorsUtils.convertDependency(pmPtMain.getPtDependency(), rule)));
        /*PO转VO*/
        List<PmPtMainVO> pmPtMainVOList = BeanConverter.copyList(pmPtMainList, PmPtMainVO.class);
        for (PmPtMainVO pmPtMainVO : pmPtMainVOList) {
            Integer permission = findPermissionByUserIdAndPtId(Long.valueOf(cloudUser.getId()), pmPtMainVO.getPtId());
            pmPtMainVO.setPermission(permission);
        }
        return pmPtMainVOList;
    }

    /**
     * 获取规则
     *
     * @param pmPtMainList 要生成规则的集合
     * @param isSerialKey  是否用序号做key
     * @return
     */
    private String getRule(List<PmPtMain> pmPtMainList, Boolean isSerialKey) {
        //定义转换规则
        Map<String, String> ruleMap = new HashMap<>();
        for (int i = 0; i < pmPtMainList.size(); i++) {
            if (isSerialKey) {
                ruleMap.put(i + 1 + "", pmPtMainList.get(i).getPtId().toString());
            } else {
                ruleMap.put(pmPtMainList.get(i).getPtId().toString(), i + 1 + "");
            }
        }
        return JSONObject.toJSONString(ruleMap);
    }

    /**
     * 任务/项目属性
     *
     * @param ptId
     * @return
     */
    @Override
    public PmPtMainAndDocVO findByTask(Long ptId, CloudUser cloudUser) {
        PmPtMainAndDocVO pmPtMainAndDocVO = new PmPtMainAndDocVO();

        PmPtMain pmPtMain = pmPtMainMapper.findById(ptId);
        //PO转VO
        PmPtMainAttributeVO pmPtMainAttributeVO = BeanConverter.copyProperties(pmPtMain, PmPtMainAttributeVO.class);
        //如果是任务
        if ("T".equals(pmPtMain.getPtPtm())) {
            //根据任务id得到配置对象
            PmPhaseTask pmPhasetask = pmPhaseTaskMapper.findByTaskId(ptId);
            //校验查询结果是否为阶段任务
            if (pmPhasetask != null) { //是
                //设置任务的阶段名称
                pmPtMainAttributeVO.setPhaseName(pmPhasetask.getPpPhaseName());
            }
            if (pmPtMain.getPtPId() != 0) {
                //查询父任务
                PmPtMain parentPmPtMain = pmPtMainMapper.findById(pmPtMain.getPtPId());
                //设置父任务Code
                pmPtMainAttributeVO.setParentPtPtCode(parentPmPtMain.getPtCode());
            }
        } else {
            //根据项目的类型id查询类型
            PmPType pmPType = pmPTypeMapper.findById(pmPtMain.getPtTypeId());
            //获得项目阶段定义，切割为数组遍历
            String pyPhase = pmPType.getPyPhase();
            //准备;发布;维护
            String[] ppPhaseNames = pyPhase.split(";");
            for (String ppPhaseName : ppPhaseNames) {
                //根据阶段名称和所属项目id查询配置记录
                PmPhaseTask pmPhasetask = pmPhaseTaskMapper.findByPpPtIdAndPpPhaseName(pmPtMain.getPtId(), ppPhaseName);
                if (pmPhasetask != null) {
                    if (pmPhasetask.getPpTaskId() != null) {
                        //根据任务id查询任务
                        PmPtMain pmPtTask = pmPtMainMapper.findById(pmPhasetask.getPpTaskId());
                        //判断任务状态
                        //状态为执行中则将项目状态设置为当前任务的状态，并跳出循环，如果已经正常完成，遍历下一条
                        if (!"E".equals(pmPtTask.getPtStatus())) {
                            //未完成
                            pmPtMainAttributeVO.setPhaseName(pmPhasetask.getPpPhaseName());
                            break;
                        }
                    }
                } else {
                    //未配置任务,项目阶段直接为null
                    pmPtMainAttributeVO.setPhaseName(ppPhaseName);
                    break;
                }
            }
            //如果定义的阶段任务均已经完成默认设置为最后阶段
            if (pmPtMainAttributeVO.getPhaseName() == null) {
                //取阶段中最后一个阶段作为项目的阶段
                pmPtMainAttributeVO.setPhaseName(ppPhaseNames[ppPhaseNames.length - 1]);
            }
        }

        //2020.5.25 新增返回权限
        Integer permission = this.findPermissionByUserIdAndPtId(Long.valueOf(cloudUser.getId()), ptId);
        pmPtMainAttributeVO.setPermission(permission);
        pmPtMainAndDocVO.setPmPtMainAttributeVO(pmPtMainAttributeVO);

        //Long ptId, String poIOType, CloudUser cloudUser   2020.5.19 新增文档部分
        String[] str = {"I", "O"};
        List<PmPtObjectResultVO> list = new ArrayList<>();
        for (int i = 0; i < str.length; i++) {
            PmPtObjectResultVO pmPtObjectResultVO = PmPtObjectService.findByPoPtIdAndPoIOType(pmPtMain.getPtId(), str[i], cloudUser);
            list.add(pmPtObjectResultVO);
        }
        pmPtMainAndDocVO.setPmPtObjectResultVOList(list);
        return pmPtMainAndDocVO;
    }


    /**
     * 递归查询子任务
     *
     * @param pmPtMainList
     * @param pmPtMain
     */
    private void recursionFindPtId(List<PmPtMain> pmPtMainList, PmPtMain pmPtMain) {
        if (null == pmPtMain) {
            throw new RuntimeException("递归查询子任务参数为空！");
        }
        //将该对象存入集合
        pmPtMainList.add(pmPtMain);
        /*设置该条记录的依赖项*/
        if ("T".equals(pmPtMain.getPtPtm())) {
            List<String> pcPIdList = new ArrayList<>();
            //根据当前任务id和后续任务状态查询约束列表(前序任务列表)
            List<PmPtCondTask> pcSIdAndPcSStatus = pmPtCondTaskMapper.selectList(Wrappers.<PmPtCondTask>lambdaQuery()
                    .eq(PmPtCondTask::getPcSId, pmPtMain.getPtId())//后续任务等于当前任务id
                    .eq(PmPtCondTask::getPcSStatus, "S"));//后续任务状态为启动
            //遍历前序任务列表
            pcSIdAndPcSStatus.forEach(pmPtCondTask -> pcPIdList.add(pmPtCondTask.getPcPId().toString()));
            //设置依赖项
            pmPtMain.setPtDependency(JSONObject.toJSONString(pcPIdList));
        } else {
            pmPtMain.setPtDependency("[]");
        }
        /*查询该项目(任务)的子任务*/
        List<PmPtMain> ptMains = pmPtMainMapper.findByPtPId(pmPtMain.getPtId());
        //遍历子任务集合列表
        for (PmPtMain ptMain : ptMains) {
            //递归
            this.recursionFindPtId(pmPtMainList, ptMain);
        }
    }


    /**
     * 指定经理人
     *
     * @param ptId
     * @param ptExecuter
     * @param cloudUser
     */
    @Override
    public void updateByExecuter(Long ptId, Long ptExecuter, CloudUser cloudUser) {
        pmPtMainMapper.updateByExecuter(ptId, ptExecuter, cloudUser);
    }

    /**
     * 个人面板
     *
     * @param pageNum
     * @param pageSize
     * @param pmPtMainPanelDTO
     * @param cloudUser
     * @return
     */
    @Override
    public PageResultVO findPanelByQuery(int pageNum, int pageSize, PmPtMainPanelDTO pmPtMainPanelDTO, CloudUser cloudUser) {
        //开启分页
        PageHelper.startPage(pageNum, pageSize);
        //获取结果集
        Page<PmPtMain> page = (Page<PmPtMain>) pmPtMainMapper.findPanelByQuery(pmPtMainPanelDTO, cloudUser);
        //创建数组
        List<PmPtMainPanelVO> pmPtMainPanelVOList = new ArrayList<>();
        for (PmPtMain pmPtMain : page.getResult()) {
            PmPtMainPanelVO pmPtMainPanelVO = BeanConverter.copyProperties(pmPtMain, PmPtMainPanelVO.class);
            pmPtMainPanelVO.setPermission(this.findPermissionByUserIdAndPtId(Long.valueOf(cloudUser.getId()), pmPtMainPanelVO.getPtId()));
            if ("P".equals(pmPtMainPanelVO.getPtPtm())) {
                //是项目
                /*(委托人)获取委托链截取最后一个字符串*/
                pmPtMainPanelVO.setPtAssignorId(Long.parseLong(pmPtMainPanelVO.getPtAssignors().substring(pmPtMainPanelVO.getPtAssignors().lastIndexOf(",") + 1)));
                //设置项目所属编号
                pmPtMainPanelVO.setPtPCode(pmPtMainPanelVO.getPtCode());
            } else {
                //是任务
                /*(委托人)获取委托链截取最后一个字符串*/
                pmPtMainPanelVO.setPtAssignorId(Long.parseLong(pmPtMainPanelVO.getPtAssignors().substring(pmPtMainPanelVO.getPtAssignors().lastIndexOf(",") + 1)));
                //查询所属项目
                PmPtMain parentPmPtMain = this.recursionProject(pmPtMainPanelVO.getPtPId());
                if (parentPmPtMain != null) {
                    pmPtMainPanelVO.setPtPCode(parentPmPtMain.getPtCode());
                    pmPtMainPanelVO.setProjectName(parentPmPtMain.getPtName());
                }

            }
            pmPtMainPanelVOList.add(pmPtMainPanelVO);
        }
        for (PmPtMainPanelVO pmPtMainPanelVO : pmPtMainPanelVOList) {
            List<PmActiveMain> pmActiveMainList = pmActiveMainMapper.findByPtId(pmPtMainPanelVO.getPtId());
            if (CollectionUtils.isNotEmpty(pmActiveMainList)) {
                //获取最新执行记录
                PmActiveMain pmActiveMain = pmActiveMainList.get(pmActiveMainList.size() - 1);
                //设置实际开始实际，实际结束时间
                pmPtMainPanelVO.setPvStartTime(pmActiveMain.getPvStartTime());
                pmPtMainPanelVO.setPvEndTime(pmActiveMain.getPvEndTime());
            }
        }
        return new PageResultVO(page.getTotal(), pmPtMainPanelVOList);
    }

    /*public static void main(String[] args) {
        int[][] arr = {{22, 15, 32, 20, 18}, {12, 21, 25, 19, 33}, {14, 58, 34, 24, 66}, {12, 21, 35, 19, 33}, {11, 21, 245, 19, 37}};
        int i = arr[0][1];
        System.err.println(i);

        *//*
           行：每个角色index
           列：对应的状态，返回的结果
         *//*
    }*/

    /**
     * 根据用户ID和任务ID，决定权限
     *
     * @param userId 用户id
     * @param ptId   任务id
     * @return
     */
    @Override
    public Integer findPermissionByUserIdAndPtId(Long userId, Long ptId) {
        //根据任务id查询当前任务
        PmPtMain pmPtMain = pmPtMainMapper.findById(ptId);
        int resStatus = 0;
        //默认状态：暂停
        int statusIndex = 5;

        /*获取当前任务的状态，列*/
        //遍历任务状态数组
        for (int i = 0; i < status.length; i++) {
            //查询状态是否为非暂停状态
            if (status[i].equals(pmPtMain.getPtStatus())) {
                //设置对应的状态索引
                statusIndex = i;
            }
        }
        /*判断是否是创建人(第一委托人)*/
        if (userId.equals(pmPtMain.getPtCreator())) {
            //得到权限状态码
            resStatus = permissionMap[0][statusIndex] | resStatus;
        }
        /*判断是否是执行人*/
        if (userId.equals(pmPtMain.getPtExecuter())) {
            resStatus = permissionMap[1][statusIndex] | resStatus;
        }
        /*中间委托人*/
        //判断是否在委托链中且不是创建人才有审核资格审核
        if (AssignorsUtils.isContains(pmPtMain.getPtAssignors(), userId + "") && AssignorsUtils.getLastIndexOf(pmPtMain.getPtAssignors(), userId + "") != 0) {
            //得到权限状态码
            resStatus = permissionMap[2][statusIndex] | resStatus;
        }
/*        //流程参与人
        if(userId.equals(pmPtMain.getPtExecuter())){
            resStatus = permissionMap[3][statusIndex] | resStatus;
        }*/
        /*项目经理*/
        //声明项目对象
        PmPtMain project;
        //判断当前对象是任务还是项目
        if ("T".equals(pmPtMain.getPtPtm()) && pmPtMain.getPtPId() != 0) {
            //查询该任务所属的项目
            project = this.recursionProject(pmPtMain.getPtPId());
        } else {
            project = pmPtMain;
        }
        //判断所属项目是否为null
        if (project != null) {
            if (userId.equals(project.getPtExecuter())) {
                resStatus = permissionMap[4][statusIndex] | resStatus;
            }
        }
        /*上级负责人*/
        //根据父id得到父任务
        if (pmPtMain.getPtPId() != 0) {
            PmPtMain ptMainParent = pmPtMainMapper.findById(pmPtMain.getPtPId());
            if (ptMainParent != null && userId.equals(ptMainParent.getPtExecuter())) {
                resStatus = permissionMap[5][statusIndex] | resStatus;
            }
        }
        /*判断该权限是否拥有审核状态码*/
        if ((resStatus & 32) != 0) {
            //判断是否轮到当前登录人审核(没轮到则关闭审核权限)
            if (!AssignorsUtils.isAudit(pmPtMain.getPtAssignors(), pmPtMain.getPtAudits(), userId + "")) {
                resStatus -= 32;
            }
        }
        System.out.println(pmPtMain.getPtName() + "[" + pmPtMain.getPtCode() + "]权限码：" + resStatus);
        return resStatus;
    }

    /**
     * 递归查询任务所属项目
     *
     * @param ptPId
     * @return
     */
    @Override
    public PmPtMain recursionProject(Long ptPId) {
        //查询当前任务的父任务
        PmPtMain parentPmPtMain = pmPtMainMapper.findById(ptPId);
        if (parentPmPtMain != null) {
            //判断父任务是否是任务
            if ("T".equals(parentPmPtMain.getPtPtm())) {
                //继续查询父任务
                parentPmPtMain = this.recursionProject(parentPmPtMain.getPtPId());
            }
        }
        //不为任务，返回当前项目、模板项目对象
        return parentPmPtMain;
    }

    /**
     * 递归查询任务所属根任务/项目
     *
     * @param ptId
     * @return
     */
    private PmPtMain recursionRootPtMain(Long ptId) {
        //查询当前任务的父任务
        PmPtMain rootPtMain = pmPtMainMapper.findById(ptId);
        if (rootPtMain != null && rootPtMain.getPtPId() != 0) {
            //继续查询父任务
            rootPtMain = this.recursionRootPtMain(rootPtMain.getPtPId());
        }
        //返回根记录对象
        return rootPtMain;
    }

    /**
     * 查询当前任务可选的启停条件列表
     *
     * @param pmPtId
     * @return
     */
    @Override
    public List<PmPtMainTaskVO> findCondTask(Long pmPtId) {
        PmPtMain currentPtMain = pmPtMainMapper.findById(pmPtId);
        /*查询当前任务的根记录的子任务列表*/
        PmPtMain rootPtMain = this.recursionRootPtMain(pmPtId);
        List<PmPtMain> ptMainList = new ArrayList<>();
        this.recursionFindPtId(ptMainList, rootPtMain);
        /*递归根据启停条件查询不能选择的任务id集合*/
        Set<Long> noSelectIds = new HashSet<>();
        //上级结构不允许
        this.recursionNoSelectByStructure(noSelectIds, pmPtId);
        //条件不允许
        this.recursionNoSelectByCondition(noSelectIds, pmPtId);
        //子级不允许
        List<PmPtMain> sonMains = new ArrayList<>();
        this.recursionFindPtId(sonMains, currentPtMain);
        sonMains.remove(0);
        sonMains.forEach(pmPtMain -> noSelectIds.add(pmPtMain.getPtId()));
        //已选择不允许
        pmPtCondTaskMapper.selectList(Wrappers.<PmPtCondTask>lambdaQuery()
                .eq(PmPtCondTask::getPcSId, pmPtId))
                .forEach(pmPtCondTask -> noSelectIds.add(pmPtCondTask.getPcPId()));
        /*过滤不允许任务*/
        List<PmPtMain> condTaskPtMains = ptMainList.stream()
                .filter(pmPtMain -> !noSelectIds.contains(pmPtMain.getPtId()))
                .collect(Collectors.toList());
        return BeanConverter.copyList(condTaskPtMains, PmPtMainTaskVO.class);
    }

    @Override
    public List<PmPtMain> findByPyId(Long pyId) {
        return pmPtMainMapper.findByPyId(pyId);
    }


    /**
     * 根据甘特图上级结构查询不能选择的任务id数组
     *
     * @param noSelectIds
     * @param pmPtId
     */
    private void recursionNoSelectByStructure(Set<Long> noSelectIds, Long pmPtId) {
        noSelectIds.add(pmPtId);
        PmPtMain pmPtMain = pmPtMainMapper.findById(pmPtId);
        if (pmPtMain != null && pmPtMain.getPtPId() != 0) {
            this.recursionNoSelectByStructure(noSelectIds, pmPtMain.getPtPId());
        }
    }

    /**
     * 根据启停条件查询不能选择的任务id数组
     *
     * @param noSelectIds 不能选择的id数组
     * @param pcPId       前序任务id
     * @return
     */
    private void recursionNoSelectByCondition(Set<Long> noSelectIds, Long pcPId) {
        noSelectIds.add(pcPId);
        List<PmPtCondTask> pmPtCondTasks = pmPtCondTaskMapper.selectList(Wrappers.<PmPtCondTask>lambdaQuery()
                .eq(PmPtCondTask::getPcPId, pcPId));
        pmPtCondTasks.forEach(pmPtCondTask -> {
            PmPtMain currentPtMain = pmPtMainMapper.findById(pmPtCondTask.getPcSId());
            List<PmPtMain> sonMains = new ArrayList<>();
            this.recursionFindPtId(sonMains, currentPtMain);
            sonMains.forEach(pmPtMain -> noSelectIds.add(pmPtMain.getPtId()));
            noSelectIds.add(pmPtCondTask.getPcSId());
            this.recursionNoSelectByCondition(noSelectIds, pmPtCondTask.getPcSId());
        });
    }

    @Override
    public ProjPageResultVO findPlanById(Integer pageNum, Integer pageSize, Long ptId, CloudUser cloudUser) {
        /*查询当前任务*/
        PmPtMain pmPtMain = pmPtMainMapper.findById(ptId);
        PmPtMainPlanVO pmPtMainPlanVO = new PmPtMainPlanVO();
        Boolean flag=false;
        /*查询当前任务的版本列表*/
        List<PmPlanVer> planVers = pmPlanVerMapper.findByPvPtId(ptId);
        for (PmPlanVer pmPlanVer : planVers) {
            if (pmPlanVer.getPvStatus().equals(PlanEnum.EDITING.getCode()) || pmPlanVer.getPvStatus().equals(PlanEnum.WAITING_AUDIT.getCode())) {
                //如果所有计划中存在某个计划的状态是编辑中或者待审核，则返回前端一个标记
                flag=true;
            }
        }
        //2020.5.27 新增分页
        PageHelper.startPage(pageNum, pageSize);
        Page<PmPlanVer> page = (Page<PmPlanVer>) pmPlanVerMapper.findByPvPtId(ptId);

        /*PO转VO*/
        PmPtMainDto pmPtMainDto = BeanConverter.copyProperties(pmPtMain, PmPtMainDto.class);
        pmPtMainPlanVO.setPmPtMainDto(pmPtMainDto);
        if (page.getResult() != null) {
            List<PmPlanVerVO> pmPlanVerVOList = BeanConverter.copyList(page.getResult(), PmPlanVerVO.class);
            pmPlanVerVOList.forEach(x -> x.setPtExecuter(pmPtMain.getPtExecuter()));

            //将版本vo列表设置到任务计划vo中
            pmPtMainPlanVO.setPmPlanVerVOList(pmPlanVerVOList);
            if (pmPlanVerVOList.size() != 0) {
                pmPtMainDto.setIsModification(!"1".equals(pmPlanVerVOList.get(pmPlanVerVOList.size() - 1).getPvStatus()));
            } else {
                pmPtMainDto.setIsModification(true);
            }
        }
        return new ProjPageResultVO(page.getTotal(), pmPtMainPlanVO.getPmPtMainDto(),flag,pmPtMainPlanVO.getPmPlanVerVOList());
    }

    @Override
    public void savePlan(PmPtMainPlanDTO pmPtMainPlanDTO, CloudUser cloudUser) {
        //根据id查询项目
        PmPtMain ptMain = pmPtMainMapper.findById(pmPtMainPlanDTO.getPtId());
        if (null == ptMain) {
            throw new RuntimeException("参数异常，查无此项目任务");
        }
        /*时间校验*/
        //判断时间是否被修改过
        if ((ptMain.getPtPlanEnd().getTime() != pmPtMainPlanDTO.getPtPlanEnd().getTime()) || (ptMain.getPtPlanStart().getTime() != pmPtMainPlanDTO.getPtPlanStart().getTime())) {
            //查询父任务
            if (ptMain.getPtPId() != 0) {
                PmPtMain parentPtMain = pmPtMainMapper.findById(ptMain.getPtPId());
                if (pmPtMainPlanDTO.getPtPlanStart().getTime() < parentPtMain.getPtPlanStart().getTime()) {
                    throw new RuntimeException("计划开始时间不可早于父任务(" + parentPtMain.getPtCode() + "),如需修改请联系项目经理于甘特图中重新规划");
                } else if (pmPtMainPlanDTO.getPtPlanEnd().getTime() > parentPtMain.getPtPlanEnd().getTime()) {
                    throw new RuntimeException("计划结束时间不可晚于父任务(" + parentPtMain.getPtCode() + "),如需修改请联系项目经理于甘特图中重新规划");
                }
            }
        }

        /*======= 获取列表变为获取单个计划版本，2020.5.22 变更 ========*/

        /*获取版本列表*/
       /* List<PmPlanVerDTO> pmPlanVerDTOList = pmPtMainPlanDTO.getPmPlanVerDTOList();
        //判断版本列表是否为空
        if (pmPlanVerDTOList == null || pmPlanVerDTOList.size() == 0)*/

        PmPlanVerDTO pmPlanDTO = pmPtMainPlanDTO.getPmPlanVerDTO();
        if (pmPlanDTO != null) {
            /*新建版本*/
            PmPlanVer pmPlanVer = new PmPlanVer();
            //任务id(外键)
            pmPlanVer.setPvPtid(pmPtMainPlanDTO.getPtId());
            //计划开始时间
            pmPlanVer.setPvStartime(pmPlanDTO.getPvStartime());
            //计划结束时间
            pmPlanVer.setPvEndtime(pmPlanDTO.getPvEndtime());
            //预估工期(天)
            pmPlanVer.setPvDuration(pmPlanDTO.getPvDuration());
            //费用预算
            pmPlanVer.setPvBudget(pmPlanDTO.getPvBudget());
            //2020.5.13 新增费用单位 申请时间 变更原因 关联评审文档id
            pmPlanVer.setPvCostunit(pmPlanDTO.getPvCostunit());
            pmPlanVer.setPvSubmittime(new Date());
            //2020.5.13 新增申请人  todo 初始化的时候申请人怎么赋值？
            if (pmPtMainPlanDTO.getPvSubmitid() != null) {
                pmPlanVer.setPvSubmitid(pmPtMainPlanDTO.getPvSubmitid());
            }
            if (pmPlanDTO.getPvPubdate() != null) {
                //这种情况属于项目启动即初始化一条变更计划
                pmPlanVer.setPvPubdate(pmPlanDTO.getPvPubdate());
            }
            if (StringUtils.isNotBlank(pmPlanDTO.getPvRemark())) {
                pmPlanVer.setPvRemark(pmPlanDTO.getPvRemark());
            }
            if (null != pmPlanDTO.getPvEcoid()) {
                pmPlanVer.setPvEcoid(pmPlanDTO.getPvEcoid());
            }

            //批准状态
            if (StringUtils.isNotBlank(pmPlanDTO.getPvStatus())) {
                pmPlanVer.setPvStatus(pmPlanDTO.getPvStatus());//这种情况属于项目启动即初始化一条变更计划，已审核
            } else {
                pmPlanVer.setPvStatus(PlanEnum.EDITING.getCode());//其他情况都是编辑中
            }
            //序号
            List<PmPlanVer> pmPlanVers = pmPlanVerMapper.findByPvPtId(ptMain.getPtId());
            if (CollectionUtils.isNotEmpty(pmPlanVers)) {
                pmPlanVer.setPvOrder(pmPlanVers.get(pmPlanVers.size() - 1).getPvOrder() + 1);
            } else {
                pmPlanVer.setPvOrder(0);
            }
            //账套id
            pmPlanVer.setPvSetSid(Long.valueOf(cloudUser.getTenantId()));
            /*新建记录到数据库*/
            pmPlanVerMapper.insert(pmPlanVer);

        }
    }


    @Override
    public List<PmPtMainTaskVO> findTaskByPtId(Long ptId) {
        //根据id查询子任务
        PmPtMain pmPtMain = pmPtMainMapper.findById(ptId);
        //定义一个集合，存放子任务列表
        List<PmPtMain> pmPtMainList = new ArrayList<>();
        //递归查询子任务
        this.recursionFindPtId(pmPtMainList, pmPtMain);
        //去除项目记录
        pmPtMainList.remove(0);
        /*PO转VO*/
        return BeanConverter.copyList(pmPtMainList, PmPtMainTaskVO.class);
    }

    /**
     * 保存任务属性
     *
     * @param pmPtMainAttributeDTO
     * @param cloudUser
     */
    @Override
    public void saveAttributeById(PmPtMainAttributeDTO pmPtMainAttributeDTO, CloudUser cloudUser) {
        //根据id查询项目
        PmPtMain ptMain = pmPtMainMapper.findById(pmPtMainAttributeDTO.getPtId());
        if (ptMain == null) {
            throw new RuntimeException("无此项目!");
        }
        //如果它不是任务,且项目类型发生改变,则删除项目阶段配置
        if (!"T".equals(ptMain.getPtPtm()) && ptMain.getPtTypeId().longValue() != pmPtMainAttributeDTO.getPtTypeId()) {
            //是，删除配置信息
            pmPhaseTaskMapper.deleteByPpPtId(ptMain.getPtId());
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String planStart = sdf.format(ptMain.getPtPlanStart());
        String planEnd = sdf.format(ptMain.getPtPlanEnd());
        //如果属性时间发生改变,则
        if (!(sdf.format(pmPtMainAttributeDTO.getPtPlanStart()).equals(planStart)) || !(sdf.format(pmPtMainAttributeDTO.getPtPlanEnd()).equals(planEnd))) {
            /*时间校验*/
            PmPtMain parentPtMain = pmPtMainMapper.findById(ptMain.getPtPId());
            if (parentPtMain != null) {
                if (pmPtMainAttributeDTO.getPtPlanStart().getTime() < parentPtMain.getPtPlanStart().getTime()) {
                    throw new RuntimeException("计划开始时间不可早于父任务(" + parentPtMain.getPtCode() + "),如需修改请联系项目经理于甘特图中重新规划");
                } else if (pmPtMainAttributeDTO.getPtPlanEnd().getTime() > parentPtMain.getPtPlanEnd().getTime()) {
                    throw new RuntimeException("计划结束时间不可晚于父任务(" + parentPtMain.getPtCode() + "),如需修改请联系项目经理于甘特图中重新规划");
                }
            }
            //修改最新计划版本的时间
            List<PmPlanVer> pmPlanVers = pmPlanVerMapper.findByPvPtId(pmPtMainAttributeDTO.getPtId());
            PmPlanVer pmPlanVer = pmPlanVers.get(pmPlanVers.size() - 1);
            if (!"1".equals(pmPlanVer.getPvStatus())) {
                pmPlanVer.setPvStartime(pmPtMainAttributeDTO.getPtPlanStart());
                pmPlanVer.setPvEndtime(pmPtMainAttributeDTO.getPtPlanEnd());
                pmPlanVerMapper.update(pmPlanVer);
            }
        }
        //dto合并po
        BeanConverter.copyProperties(pmPtMainAttributeDTO, ptMain);
        pmPtMainMapper.update(ptMain, cloudUser);
    }

    /**
     * 查询模板页
     *
     * @param pageNum                  当前页码
     * @param pageSize                 每页大小
     * @param pmPtMainTemplateQueryDTO 查询对象
     * @return
     */
    @Override
    public PageResultVO findTemplateByQuery(int pageNum, int pageSize, PmPtMainTemplateQueryDTO pmPtMainTemplateQueryDTO, CloudUser cloudUser) {
        PageHelper.startPage(pageNum, pageSize);
        Page<PmPtMain> page = (Page<PmPtMain>) pmPtMainMapper.findTemplateByQuery(pmPtMainTemplateQueryDTO, cloudUser);
        /*PO转VO*/
        List<PmPtMainTemplateQueryVO> pmPtMainTemplateQueryVOList = BeanConverter.copyList(page.getResult(), PmPtMainTemplateQueryVO.class);
        return new PageResultVO(page.getTotal(), pmPtMainTemplateQueryVOList);
    }

    /**
     * 批量删除
     *
     * @param ptIds 模板id数组
     * @return
     */
    @Override
    public void deletePL(Long[] ptIds, CloudUser cloudUser) {
        //遍历id数组
        for (Long ptId : ptIds) {
            //调用单个删除
            this.deleteById(ptId, cloudUser);
        }
    }

    /**
     * 修改模板的状态
     *
     * @param ptId     模板id
     * @param ptStatus 模板要修改的状态 TA -> TB <-> TC
     * @return
     */
    @Override
    public void updateTemplateStatus(Long ptId, String ptStatus, CloudUser cloudUser) {
        //根据id查询模板
        PmPtMain template = pmPtMainMapper.findById(ptId);
        //判断要停用模板
        if ("TC".equals(ptStatus)) {
            //校验是否达到要求
            if (!"TB".equals(template.getPtStatus())) {
                throw new RuntimeException("该模板未启用,无法停用");
            }
        }
        //修改模板状态
        template.setPtStatus(ptStatus);
        //存储到数据库
        pmPtMainMapper.update(template, cloudUser);
    }

    /**
     * 使用模板
     *
     * @param ptId 模板id
     * @return
     */
    @Override
    public void useTemplate(Long ptId, CloudUser cloudUser) {
        /*定义map集合用于存储需要改动的id信息*/
        //该Map集合键为模板所用的项目或任务id，值为复制后的项目或任务id
        Map<Long, Long> ptIdMap = new HashMap<>();
        /*copy模板项目、子任务*/
        //根据id查询模板项目
        PmPtMain pmPtMain = pmPtMainMapper.findById(ptId);
        //校验模板是否启用
        if (!"TB".equals(pmPtMain.getPtStatus())) {
            throw new RuntimeException("模板未启用,无法使用模板");
        }
        //定义集合,存放模板项目和子任务
        List<PmPtMain> templateList = new ArrayList<>();
        //递归查询子任务
        this.recursionFindPtId(templateList, pmPtMain);
        //遍历集合
        for (PmPtMain template : templateList) {
            //将模板内容复制到新项目对象中
            PmPtMain ptMain = BeanConverter.copyProperties(template, PmPtMain.class);
            //清空主键
            ptMain.setPtId(null);
            //重置状态
            ptMain.setPtStatus("A");
            //判断是否为模板任务
            if ("T".equals(ptMain.getPtPtm())) {
                //设置父任务ID
                ptMain.setPtPId(ptIdMap.get(ptMain.getPtPId()));
                //设置任务编号
                ptMain.setPtCode(ProjectCodeUtils.getCode(CodeType.TASK));
            } else {
                //设置项目编号
                ptMain.setPtCode(ProjectCodeUtils.getCode(CodeType.PROJECT));
            }
            //修改结束时间
            ptMain.setPtPlanEnd(new Date());
            //修改模板标记
            ptMain.setPtIsTemplate(false);
            //修改负责人
            ptMain.setPtExecuter(null);
            //修改委托链
            ptMain.setPtAssignors(cloudUser.getId() + "");
            ptMain.setPtCreator(Long.valueOf(cloudUser.getId()));
            //插入到数据库
            pmPtMainMapper.insert(ptMain, cloudUser);
            //将旧项目id和新项目id存入map中
            ptIdMap.put(template.getPtId(), ptMain.getPtId());
            /*copy输入文档、输出文档*/
            //调用方法，查询模板项目的所有IO文档对象列表
            List<PmPtObject> ptObjectList = this.getPmPtObjectList(template.getPtId(), cloudUser);
            //遍历IO文档对象集合
            for (PmPtObject pmPtObject : ptObjectList) {
                //清空主键
                pmPtObject.setPoId(null);
                //设置任务id
                pmPtObject.setPoPtId(ptMain.getPtId());
                /**
                 * @Tip:此处存储到数据库的来源任务id所使用的仍然是模板中的任务id，后续需要修改为复制后的任务id
                 */
                //存储到数据库
                pmPtObjectMapper.insert(pmPtObject, cloudUser);
            }
            /*copy计划*/
            //查询当前任务的版本列表
            List<PmPlanVer> pmPlanVerList = pmPlanVerMapper.findByPvPtId(template.getPtId());
            //遍历版本计划
            for (PmPlanVer pmPlanVer : pmPlanVerList) {
                //清空主键
                pmPlanVer.setPvId(null);
                //设置所属任务id
                pmPlanVer.setPvPtid(ptMain.getPtId());
                //存储到数据库
                pmPlanVerMapper.insert(pmPlanVer);
            }
            //判断是否为模板项目
            if ("P".equals(template.getPtPtm())) {
                /*copy项目阶段配置*/
                //查询该模板的项目阶段配置
                List<PmPhaseTask> pmPhaseTaskList = pmPhaseTaskMapper.findByPpPtId(template.getPtId());
                //遍历阶段配置列表
                for (PmPhaseTask pmPhaseTask : pmPhaseTaskList) {
                    //清空主键
                    pmPhaseTask.setPpId(null);
                    //设置所属项目id
                    pmPhaseTask.setPpPtId(ptIdMap.get(pmPhaseTask.getPpPtId()));
                    /**
                     * @Tip:此处存储到数据库的阶段任务ID所使用的仍然是模板中的任务id，后续需要修改为复制后的任务id
                     */
                    pmPhaseTaskMapper.insert(pmPhaseTask);
                }
                /*copy项目团队配置*/
                //查询该模板的项目团队配置
                List<PmPMember> pmPMemberList = pmPMemberMapper.findByPbPtId(template.getPtId(), cloudUser);
                //遍历团队配置列表
                for (PmPMember pmPMember : pmPMemberList) {
                    //清空主键
                    pmPMember.setPbId(null);
                    //设置所属项目id
                    pmPMember.setPbPtId(ptIdMap.get(pmPMember.getPbPtId()));
                    //插入到数据库
                    pmPMemberMapper.insert(pmPMember, cloudUser);
                }
            } else {
                /*copy启停条件*/
                //根据模板中的id查询当前任务的启停条件
                List<PmPtCondTask> pmPtCondTaskList = pmPtCondTaskMapper.selectList(Wrappers.<PmPtCondTask>lambdaQuery()
                        .eq(PmPtCondTask::getPcSId, template.getPtId())
                        .eq(PmPtCondTask::getPcSStatus, "S"));
                //遍历启停条件列表
                for (PmPtCondTask pmPtCondTask : pmPtCondTaskList) {
                    //清空主键
                    pmPtCondTask.setPcId(null);
                    //设置后续任务Id
                    pmPtCondTask.setPcSId(ptMain.getPtId());
                    /**
                     * @Tip:此处存储到数据库的前序任务id所使用的仍然是模板中的任务id，后续需要修改为复制后的任务id
                     */
                    //存储到数据库
                    pmPtCondTaskMapper.insert(pmPtCondTask);
                }
            }
        }
        /*修改错误的信息*/
        //根据使用模板的项目id查询项目
        PmPtMain newPmPtMain = pmPtMainMapper.findById(ptIdMap.get(ptId));
        //定义集合,存放模板项目和子任务
        List<PmPtMain> pmPtMainList = new ArrayList<>();
        //递归查询子任务
        this.recursionFindPtId(pmPtMainList, newPmPtMain);
        //遍历列表
        for (PmPtMain newPtMain : pmPtMainList) {
            //判断是项目还是任务
            if ("P".equals(newPtMain.getPtPtm())) {
                /*修改错误的阶段配置的任务id*/
                //根据模板中的id查询当前项目的阶段配置
                List<PmPhaseTask> pmPhaseTaskList = pmPhaseTaskMapper.findByPpPtId(newPtMain.getPtId());
                //遍历阶段配置列表
                for (PmPhaseTask pmPhaseTask : pmPhaseTaskList) {
                    //设置阶段任务id
                    pmPhaseTask.setPpTaskId(ptIdMap.get(pmPhaseTask.getPpTaskId()));
                    //保存修改到数据库
                    pmPhaseTaskMapper.update(pmPhaseTask);
                }
            } else {
                /*修改错误的启停条件前序任务id*/
                //根据模板中的id查询当前任务的启停条件
                List<PmPtCondTask> pmPtCondTaskList = pmPtCondTaskMapper.selectList(Wrappers.<PmPtCondTask>lambdaQuery()
                        .eq(PmPtCondTask::getPcSId, newPtMain.getPtId())
                        .eq(PmPtCondTask::getPcSStatus, "S"));
                //遍历启停条件列表
                pmPtCondTaskList.forEach(pmPtCondTask -> {
                    //设置前续任务Id
                    pmPtCondTask.setPcPId(ptIdMap.get(pmPtCondTask.getPcPId()));
                    //保存修改到数据库
                    pmPtCondTaskMapper.updateById(pmPtCondTask);
                });
            }
            /*修改错误的输入、输出文档的来源任务id*/
            //查询复制后项目的所有IO文档对象列表
            List<PmPtObject> pmPtObjectList = this.getPmPtObjectList(newPtMain.getPtId(), cloudUser);
            //遍历集合
            for (PmPtObject pmPtObject : pmPtObjectList) {
                //判断来源id是否不为空
                if (pmPtObject.getPoSourceId() != null) {
                    //重新设置来源id
                    pmPtObject.setPoSourceId(ptIdMap.get(pmPtObject.getPoSourceId()));
                    //更新到数据库
                    pmPtObjectMapper.update(pmPtObject, cloudUser);
                }
            }
        }
    }


    /**
     * 查询项目所有的IO文档对象列表
     *
     * @param ptId
     * @param cloudUser
     * @return
     */
    private List<PmPtObject> getPmPtObjectList(Long ptId, CloudUser cloudUser) {
        //创建输入文档类型集合
        List<PmPtObject> objectITypeList = new ArrayList<>();
        //创建输入文档集合
        List<PmPtObject> objectIList = new ArrayList<>();
        //创建输出文档类型集合
        List<PmPtObject> objectOTypeList = new ArrayList<>();
        //创建输出文档集合
        List<PmPtObject> objectOList = new ArrayList<>();
        //递归查询输入文档类型列表
        pmPtObjectServiceImpl.recursionIODoccTypeOrIODocVer(ptId, "I", true, objectITypeList, cloudUser);
        //递归查询输入文档列表
        pmPtObjectServiceImpl.recursionIODoccTypeOrIODocVer(ptId, "I", false, objectIList, cloudUser);
        //递归查询输出文档类型列表
        pmPtObjectServiceImpl.recursionIODoccTypeOrIODocVer(ptId, "O", true, objectOTypeList, cloudUser);
        //递归查询输出文档列表
        pmPtObjectServiceImpl.recursionIODoccTypeOrIODocVer(ptId, "O", false, objectOList, cloudUser);
        //创建集合，存放所有查询出来的IO文档对象
        List<PmPtObject> ptObjectList = new ArrayList<>();
        ptObjectList.addAll(objectITypeList);
        ptObjectList.addAll(objectIList);
        ptObjectList.addAll(objectOTypeList);
        ptObjectList.addAll(objectOList);
        return ptObjectList;
    }

    /**
     * 查询所有模板列表
     *
     * @param ptName 模板名称
     * @return
     */
    @Override
    public List<PmPtMainTemplateQueryVO> findTemplateListByPtName(String ptName, CloudUser cloudUser) {
        List<PmPtMain> pmPtMainList = pmPtMainMapper.findTemplateListByPtName(ptName, cloudUser);
        //PO转VO
        return BeanConverter.copyList(pmPtMainList, PmPtMainTemplateQueryVO.class);
    }


    /**
     * 新建任务-个人面板
     *
     * @param pmPtMainInsertTaskDTO
     */
    @Override
    public void insertTask(PmPtMainInsertTaskDTO pmPtMainInsertTaskDTO, CloudUser cloudUser) {
        /*DTO转PO*/
        PmPtMain pmPtMain = BeanConverter.copyProperties(pmPtMainInsertTaskDTO, PmPtMain.class);
        //判断扩展属性集是否为空
        if (pmPtMain.getPtPropsets() == null || "".equals(pmPtMain.getPtPropsets())) {
            pmPtMain.setPtPropsets("{}");
        }
        //判断父任务id是否为空
        if (pmPtMain.getPtPId() == null) {
            //设置父任务id为0
            pmPtMain.setPtPId(0L);
        }
        //任务委托人用户ID链
        pmPtMain.setPtAssignors(cloudUser.getId() + "");
        //里程碑标记
        pmPtMain.setPtMilestone(false);
        //任务状态
        pmPtMain.setPtStatus("A");
        //任务类别
        pmPtMain.setPtPtm("T");
        //删除标记
        pmPtMain.setPtDelFlag(false);
        //项目进度
        pmPtMain.setPtProgress(0);
        //模板 2020.5.22
        pmPtMain.setPtIsTemplate(false);

        //根据生成器生成模板任务编号  2020.5.22
        pmPtMain.setPtCode(ProjectCodeUtils.getCode(CodeType.TASK));

        pmPtMain.setPtCreator(Long.valueOf(cloudUser.getId()));
        //根据父任务id查询项目
        PmPtMain parentPtMain = pmPtMainMapper.findById(pmPtMain.getPtPId());
        //判断父任务是否为空
        if (parentPtMain == null) {
            /*设置任务的排序号*/
            pmPtMain.setPtOrder("1");
            //插入任务获取该记录的id
            pmPtMainMapper.insert(pmPtMain, cloudUser);
        } else {
            /*时间合法校验*/
            if (pmPtMainInsertTaskDTO.getPtPlanStart().getTime() < parentPtMain.getPtPlanStart().getTime()) {
                throw new RuntimeException("计划开始时间不可早于父任务(" + parentPtMain.getPtCode() + "),如需修改请联系项目经理于甘特图中重新规划");
            } else if (pmPtMainInsertTaskDTO.getPtPlanEnd().getTime() > parentPtMain.getPtPlanEnd().getTime()) {
                throw new RuntimeException("计划结束时间不可晚于父任务(" + parentPtMain.getPtCode() + "),如需修改请联系项目经理于甘特图中重新规划");
            }
            /*设置任务的排序号*/
            //查询父任务的子任务列表
            List<PmPtMain> sonTaskList = pmPtMainMapper.findByPtPId(pmPtMain.getPtPId());
            //声明新任务的排序号
            String ptOrder;
            //校验子任务列表是否为空
            if (sonTaskList != null && sonTaskList.size() != 0) {
                //将子任务列表按照排序字段排序
                Collections.sort(sonTaskList, new PtOrderComparator());
                //获取最后一条任务的ptOrder
                String lastPtOrder = sonTaskList.get(sonTaskList.size() - 1).getPtOrder();
                //截取最后一个序号并自增
                Integer orderNum = Integer.parseInt(lastPtOrder.substring(lastPtOrder.lastIndexOf(".") + 1)) + 1;
                //拼接新任务的排序号
                ptOrder = lastPtOrder.substring(0, lastPtOrder.lastIndexOf(".") + 1) + orderNum;
            } else {
                //拼接新任务的排序号
                ptOrder = parentPtMain.getPtOrder() + ".1";
            }
            //设置到对象中
            pmPtMain.setPtOrder(ptOrder);
            //插入任务获取该记录的id
            pmPtMainMapper.insert(pmPtMain, cloudUser);
        }
        PmTaskAudit pmTaskAudit = new PmTaskAudit();
        /*存入日志*/
        this.insertPmTaskLog(pmPtMain, pmTaskAudit, cloudUser, "新建任务");
    }

    /**
     * 个人面板-选择父任务列表
     *
     * @param pageNum
     * @param pageSize
     * @param ptName
     * @return
     */
    @Override
    public PageResultVO findParentByPtName(int pageNum, int pageSize, String ptName, CloudUser cloudUser) {
        //开启分页插件
        PageHelper.startPage(pageNum, pageSize);
        //获取结果集
        Page<PmPtMain> page = (Page<PmPtMain>) pmPtMainMapper.findParentByPtName(ptName, cloudUser);
        //po转vo
        List<PmPtMainParentVO> pmPtMainParentVOList = BeanConverter.copyList(page.getResult(), PmPtMainParentVO.class);
        for (PmPtMainParentVO pmPtMainParentVO : pmPtMainParentVOList) {
            if (pmPtMainParentVO.getPtPId() == 0) {
                //设置项目所属编号
                pmPtMainParentVO.setPtPCode(pmPtMainParentVO.getPtCode());
            } else {
                /*获取任务对应的项目编号*/
                PmPtMain project = this.recursionProject(pmPtMainParentVO.getPtPId());
                if (project != null) {
                    pmPtMainParentVO.setPtPCode(project.getPtCode());
                }
            }
        }
        //返回数据
        return new PageResultVO(page.getTotal(), pmPtMainParentVOList);
    }

    /**
     * 获取项目/任务编号
     *
     * @param ptPtm
     * @return
     */
    @Override
    public String getProjectCode(String ptPtm) {
        return ProjectCodeUtils.getCode("P".equals(ptPtm) ? CodeType.PROJECT : CodeType.TASK);
    }

    /**
     * 获取模板项目编号
     *
     * @return
     */
    @Override
    public String getTemplateCode() {
        return ProjectCodeUtils.getCode(CodeType.TEMPLATE_PROJECT);
    }

}
